summaryrefslogtreecommitdiff
path: root/ruby_1_8_5/ext/openssl
diff options
context:
space:
mode:
Diffstat (limited to 'ruby_1_8_5/ext/openssl')
-rw-r--r--ruby_1_8_5/ext/openssl/.cvsignore5
-rw-r--r--ruby_1_8_5/ext/openssl/extconf.rb123
-rw-r--r--ruby_1_8_5/ext/openssl/lib/net/ftptls.rb43
-rw-r--r--ruby_1_8_5/ext/openssl/lib/net/telnets.rb248
-rw-r--r--ruby_1_8_5/ext/openssl/lib/openssl.rb24
-rw-r--r--ruby_1_8_5/ext/openssl/lib/openssl/bn.rb35
-rw-r--r--ruby_1_8_5/ext/openssl/lib/openssl/buffering.rb239
-rw-r--r--ruby_1_8_5/ext/openssl/lib/openssl/cipher.rb58
-rw-r--r--ruby_1_8_5/ext/openssl/lib/openssl/digest.rb49
-rw-r--r--ruby_1_8_5/ext/openssl/lib/openssl/ssl.rb135
-rw-r--r--ruby_1_8_5/ext/openssl/lib/openssl/x509.rb154
-rw-r--r--ruby_1_8_5/ext/openssl/openssl_missing.c345
-rw-r--r--ruby_1_8_5/ext/openssl/openssl_missing.h130
-rw-r--r--ruby_1_8_5/ext/openssl/ossl.c476
-rw-r--r--ruby_1_8_5/ext/openssl/ossl.h226
-rw-r--r--ruby_1_8_5/ext/openssl/ossl_asn1.c1166
-rw-r--r--ruby_1_8_5/ext/openssl/ossl_asn1.h59
-rw-r--r--ruby_1_8_5/ext/openssl/ossl_bio.c73
-rw-r--r--ruby_1_8_5/ext/openssl/ossl_bio.h21
-rw-r--r--ruby_1_8_5/ext/openssl/ossl_bn.c715
-rw-r--r--ruby_1_8_5/ext/openssl/ossl_bn.h22
-rw-r--r--ruby_1_8_5/ext/openssl/ossl_cipher.c406
-rw-r--r--ruby_1_8_5/ext/openssl/ossl_cipher.h23
-rw-r--r--ruby_1_8_5/ext/openssl/ossl_config.c462
-rw-r--r--ruby_1_8_5/ext/openssl/ossl_config.h22
-rw-r--r--ruby_1_8_5/ext/openssl/ossl_digest.c294
-rw-r--r--ruby_1_8_5/ext/openssl/ossl_digest.h23
-rw-r--r--ruby_1_8_5/ext/openssl/ossl_engine.c393
-rw-r--r--ruby_1_8_5/ext/openssl/ossl_engine.h20
-rw-r--r--ruby_1_8_5/ext/openssl/ossl_hmac.c220
-rw-r--r--ruby_1_8_5/ext/openssl/ossl_hmac.h19
-rw-r--r--ruby_1_8_5/ext/openssl/ossl_ns_spki.c256
-rw-r--r--ruby_1_8_5/ext/openssl/ossl_ns_spki.h21
-rw-r--r--ruby_1_8_5/ext/openssl/ossl_ocsp.c769
-rw-r--r--ruby_1_8_5/ext/openssl/ossl_ocsp.h24
-rw-r--r--ruby_1_8_5/ext/openssl/ossl_pkcs12.c154
-rw-r--r--ruby_1_8_5/ext/openssl/ossl_pkcs12.h16
-rw-r--r--ruby_1_8_5/ext/openssl/ossl_pkcs5.h6
-rw-r--r--ruby_1_8_5/ext/openssl/ossl_pkcs7.c993
-rw-r--r--ruby_1_8_5/ext/openssl/ossl_pkcs7.h23
-rw-r--r--ruby_1_8_5/ext/openssl/ossl_pkey.c232
-rw-r--r--ruby_1_8_5/ext/openssl/ossl_pkey.h120
-rw-r--r--ruby_1_8_5/ext/openssl/ossl_pkey_dh.c458
-rw-r--r--ruby_1_8_5/ext/openssl/ossl_pkey_dsa.c417
-rw-r--r--ruby_1_8_5/ext/openssl/ossl_pkey_rsa.c513
-rw-r--r--ruby_1_8_5/ext/openssl/ossl_rand.c130
-rw-r--r--ruby_1_8_5/ext/openssl/ossl_rand.h20
-rw-r--r--ruby_1_8_5/ext/openssl/ossl_ssl.c937
-rw-r--r--ruby_1_8_5/ext/openssl/ossl_ssl.h21
-rw-r--r--ruby_1_8_5/ext/openssl/ossl_version.h16
-rw-r--r--ruby_1_8_5/ext/openssl/ossl_x509.c104
-rw-r--r--ruby_1_8_5/ext/openssl/ossl_x509.h114
-rw-r--r--ruby_1_8_5/ext/openssl/ossl_x509attr.c249
-rw-r--r--ruby_1_8_5/ext/openssl/ossl_x509cert.c671
-rw-r--r--ruby_1_8_5/ext/openssl/ossl_x509crl.c535
-rw-r--r--ruby_1_8_5/ext/openssl/ossl_x509ext.c456
-rw-r--r--ruby_1_8_5/ext/openssl/ossl_x509name.c344
-rw-r--r--ruby_1_8_5/ext/openssl/ossl_x509req.c466
-rw-r--r--ruby_1_8_5/ext/openssl/ossl_x509revoked.c229
-rw-r--r--ruby_1_8_5/ext/openssl/ossl_x509store.c613
-rw-r--r--ruby_1_8_5/ext/openssl/ruby_missing.h18
61 files changed, 15153 insertions, 0 deletions
diff --git a/ruby_1_8_5/ext/openssl/.cvsignore b/ruby_1_8_5/ext/openssl/.cvsignore
new file mode 100644
index 0000000000..3a9a9f341f
--- /dev/null
+++ b/ruby_1_8_5/ext/openssl/.cvsignore
@@ -0,0 +1,5 @@
+GNUmakefile
+Makefile
+mkmf.log
+dep
+extconf.h
diff --git a/ruby_1_8_5/ext/openssl/extconf.rb b/ruby_1_8_5/ext/openssl/extconf.rb
new file mode 100644
index 0000000000..b2c5ca5ef8
--- /dev/null
+++ b/ruby_1_8_5/ext/openssl/extconf.rb
@@ -0,0 +1,123 @@
+=begin
+= $RCSfile: extconf.rb,v $ -- Generator for Makefile
+
+= Info
+ 'OpenSSL for Ruby 2' project
+ Copyright (C) 2002 Michal Rokos <m.rokos@sh.cvut.cz>
+ All rights reserved.
+
+= Licence
+ This program is licenced under the same licence as Ruby.
+ (See the file 'LICENCE'.)
+
+= Version
+ $Id: extconf.rb,v 1.21.2.9 2006/06/20 11:18:15 gotoyuzo Exp $
+=end
+
+require "mkmf"
+
+dir_config("openssl")
+dir_config("kerberos")
+
+message "=== OpenSSL for Ruby configurator ===\n"
+
+##
+# Adds -Wall -DOSSL_DEBUG for compilation and some more targets when GCC is used
+# To turn it on, use: --with-debug or --enable-debug
+#
+if with_config("debug") or enable_config("debug")
+ $defs.push("-DOSSL_DEBUG") unless $defs.include? "-DOSSL_DEBUG"
+
+ if /gcc/ =~ CONFIG["CC"]
+ $CPPFLAGS += " -Wall" unless $CPPFLAGS.split.include? "-Wall"
+ end
+end
+
+message "=== Checking for system dependent stuff... ===\n"
+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
+ have_library("wsock32")
+ have_library("gdi32")
+end
+result = have_header("openssl/ssl.h")
+result &&= %w[crypto libeay32].any? {|lib| have_library(lib, "OpenSSL_add_all_digests")}
+result &&= %w[ssl ssleay32].any? {|lib| have_library(lib, "SSL_library_init")}
+if !result
+ unless pkg_config("openssl") and have_header("openssl/ssl.h")
+ message "=== Checking for required stuff failed. ===\n"
+ message "Makefile wasn't created. Fix the errors above.\n"
+ exit 1
+ end
+end
+
+unless have_header("openssl/conf_api.h")
+ message "OpenSSL 0.9.6 or later required.\n"
+ exit 1
+end
+
+message "=== Checking for OpenSSL features... ===\n"
+have_func("ERR_peek_last_error")
+have_func("BN_mod_add")
+have_func("BN_mod_sqr")
+have_func("BN_mod_sub")
+have_func("BN_pseudo_rand_range")
+have_func("BN_rand_range")
+have_func("CONF_get1_default_config_file")
+have_func("EVP_CIPHER_CTX_copy")
+have_func("EVP_CIPHER_CTX_set_padding")
+have_func("EVP_CipherFinal_ex")
+have_func("EVP_CipherInit_ex")
+have_func("EVP_DigestFinal_ex")
+have_func("EVP_DigestInit_ex")
+have_func("EVP_MD_CTX_cleanup")
+have_func("EVP_MD_CTX_create")
+have_func("EVP_MD_CTX_destroy")
+have_func("EVP_MD_CTX_init")
+have_func("HMAC_CTX_cleanup")
+have_func("HMAC_CTX_copy")
+have_func("HMAC_CTX_init")
+have_func("PEM_def_callback")
+have_func("X509V3_set_nconf")
+have_func("X509V3_EXT_nconf_nid")
+have_func("X509_CRL_add0_revoked")
+have_func("X509_CRL_set_issuer_name")
+have_func("X509_CRL_set_version")
+have_func("X509_CRL_sort")
+have_func("X509_STORE_get_ex_data")
+have_func("X509_STORE_set_ex_data")
+have_func("OBJ_NAME_do_all_sorted")
+have_func("OPENSSL_cleanse")
+if try_compile("#define FOO(a, ...) foo(a, ##__VA_ARGS__)\n int x(){FOO(1);FOO(1,2);FOO(1,2,3);}\n")
+ $defs.push("-DHAVE_VA_ARGS_MACRO")
+end
+if have_header("openssl/engine.h")
+ have_func("ENGINE_add")
+ have_func("ENGINE_load_builtin_engines")
+ have_func("ENGINE_load_openbsd_dev_crypto")
+ have_func("ENGINE_get_digest")
+ have_func("ENGINE_get_cipher")
+ have_func("ENGINE_cleanup")
+end
+if try_compile(<<SRC)
+#include <openssl/opensslv.h>
+#if OPENSSL_VERSION_NUMBER < 0x00907000L
+# error "OpenSSL version is less than 0.9.7."
+#endif
+SRC
+ have_header("openssl/ocsp.h")
+end
+have_struct_member("EVP_CIPHER_CTX", "flags", "openssl/evp.h")
+have_struct_member("EVP_CIPHER_CTX", "engine", "openssl/evp.h")
+have_struct_member("X509_ATTRIBUTE", "single", "openssl/x509.h")
+
+message "=== Checking done. ===\n"
+
+create_header
+create_makefile("openssl")
+message "Done.\n"
diff --git a/ruby_1_8_5/ext/openssl/lib/net/ftptls.rb b/ruby_1_8_5/ext/openssl/lib/net/ftptls.rb
new file mode 100644
index 0000000000..43cc136bf6
--- /dev/null
+++ b/ruby_1_8_5/ext/openssl/lib/net/ftptls.rb
@@ -0,0 +1,43 @@
+=begin
+= $RCSfile: ftptls.rb,v $ -- SSL/TLS enhancement for Net::HTTP.
+
+= Info
+ 'OpenSSL for Ruby 2' project
+ Copyright (C) 2003 Blaz Grilc <farmer@gmx.co.uk>
+ All rights reserved.
+
+= Licence
+ This program is licenced under the same licence as Ruby.
+ (See the file 'LICENCE'.)
+
+= Requirements
+
+= Version
+ $Id: ftptls.rb,v 1.1 2003/07/23 16:11:30 gotoyuzo Exp $
+
+= Notes
+ Tested on FreeBSD 5-CURRENT and 4-STABLE
+ - ruby 1.6.8 (2003-01-17) [i386-freebsd5]
+ - OpenSSL 0.9.7a Feb 19 2003
+ - ruby-openssl-0.2.0.p0
+ tested on ftp server: glftpd 1.30
+=end
+
+require 'socket'
+require 'openssl'
+require 'net/ftp'
+
+module Net
+ class FTPTLS < FTP
+ def login(user = "anonymous", passwd = nil, acct = nil)
+ ctx = OpenSSL::SSL::SSLContext.new('SSLv23')
+ ctx.key = nil
+ ctx.cert = nil
+ voidcmd("AUTH TLS")
+ @sock = OpenSSL::SSL::SSLSocket.new(@sock, ctx)
+ @sock.connect
+ super(user, passwd, acct)
+ voidcmd("PBSZ 0")
+ end
+ end
+end
diff --git a/ruby_1_8_5/ext/openssl/lib/net/telnets.rb b/ruby_1_8_5/ext/openssl/lib/net/telnets.rb
new file mode 100644
index 0000000000..d277a5c2a6
--- /dev/null
+++ b/ruby_1_8_5/ext/openssl/lib/net/telnets.rb
@@ -0,0 +1,248 @@
+=begin
+= $RCSfile: telnets.rb,v $ -- SSL/TLS enhancement for Net::Telnet.
+
+= Info
+ 'OpenSSL for Ruby 2' project
+ Copyright (C) 2001 GOTOU YUUZOU <gotoyuzo@notwork.org>
+ All rights reserved.
+
+= Licence
+ This program is licenced under the same licence as Ruby.
+ (See the file 'LICENCE'.)
+
+= Version
+ $Id: telnets.rb,v 1.1.2.1 2004/12/20 03:49:16 gotoyuzo Exp $
+
+ 2001/11/06: Contiributed to Ruby/OpenSSL project.
+
+== class Net::Telnet
+
+This class will initiate SSL/TLS session automaticaly if the server
+sent OPT_STARTTLS. Some options are added for SSL/TLS.
+
+ host = Net::Telnet::new({
+ "Host" => "localhost",
+ "Port" => "telnets",
+ ## follows are new options.
+ 'CertFile' => "user.crt",
+ 'KeyFile' => "user.key",
+ 'CAFile' => "/some/where/certs/casert.pem",
+ 'CAPath' => "/some/where/caserts",
+ 'VerifyMode' => SSL::VERIFY_PEER,
+ 'VerifyCallback' => verify_proc
+ })
+
+Or, the new options ('Cert', 'Key' and 'CACert') are available from
+Michal Rokos's OpenSSL module.
+
+ cert_data = File.open("user.crt"){|io| io.read }
+ pkey_data = File.open("user.key"){|io| io.read }
+ cacert_data = File.open("your_ca.pem"){|io| io.read }
+ host = Net::Telnet::new({
+ "Host" => "localhost",
+ "Port" => "telnets",
+ 'Cert' => OpenSSL::X509::Certificate.new(cert_data)
+ 'Key' => OpenSSL::PKey::RSA.new(pkey_data)
+ 'CACert' => OpenSSL::X509::Certificate.new(cacert_data)
+ 'CAFile' => "/some/where/certs/casert.pem",
+ 'CAPath' => "/some/where/caserts",
+ 'VerifyMode' => SSL::VERIFY_PEER,
+ 'VerifyCallback' => verify_proc
+ })
+
+This class is expected to be a superset of usual Net::Telnet.
+=end
+
+require "net/telnet"
+require "openssl"
+
+module Net
+ class Telnet
+ attr_reader :ssl
+
+ OPT_STARTTLS = 46.chr # "\056" # "\x2e" # Start TLS
+ TLS_FOLLOWS = 1.chr # "\001" # "\x01" # FOLLOWS (for STARTTLS)
+
+ alias preprocess_orig preprocess
+
+ def ssl?; @ssl; end
+
+ def preprocess(string)
+ # combine CR+NULL into CR
+ string = string.gsub(/#{CR}#{NULL}/no, CR) if @options["Telnetmode"]
+
+ # combine EOL into "\n"
+ string = string.gsub(/#{EOL}/no, "\n") unless @options["Binmode"]
+
+ string.gsub(/#{IAC}(
+ [#{IAC}#{AO}#{AYT}#{DM}#{IP}#{NOP}]|
+ [#{DO}#{DONT}#{WILL}#{WONT}][#{OPT_BINARY}-#{OPT_EXOPL}]|
+ #{SB}[#{OPT_BINARY}-#{OPT_EXOPL}]
+ (#{IAC}#{IAC}|[^#{IAC}])+#{IAC}#{SE}
+ )/xno) do
+ if IAC == $1 # handle escaped IAC characters
+ IAC
+ elsif AYT == $1 # respond to "IAC AYT" (are you there)
+ self.write("nobody here but us pigeons" + EOL)
+ ''
+ elsif DO[0] == $1[0] # respond to "IAC DO x"
+ if OPT_BINARY[0] == $1[1]
+ @telnet_option["BINARY"] = true
+ self.write(IAC + WILL + OPT_BINARY)
+ elsif OPT_STARTTLS[0] == $1[1]
+ self.write(IAC + WILL + OPT_STARTTLS)
+ self.write(IAC + SB + OPT_STARTTLS + TLS_FOLLOWS + IAC + SE)
+ else
+ self.write(IAC + WONT + $1[1..1])
+ end
+ ''
+ elsif DONT[0] == $1[0] # respond to "IAC DON'T x" with "IAC WON'T x"
+ self.write(IAC + WONT + $1[1..1])
+ ''
+ elsif WILL[0] == $1[0] # respond to "IAC WILL x"
+ if OPT_BINARY[0] == $1[1]
+ self.write(IAC + DO + OPT_BINARY)
+ elsif OPT_ECHO[0] == $1[1]
+ self.write(IAC + DO + OPT_ECHO)
+ elsif OPT_SGA[0] == $1[1]
+ @telnet_option["SGA"] = true
+ self.write(IAC + DO + OPT_SGA)
+ else
+ self.write(IAC + DONT + $1[1..1])
+ end
+ ''
+ elsif WONT[0] == $1[0] # respond to "IAC WON'T x"
+ if OPT_ECHO[0] == $1[1]
+ self.write(IAC + DONT + OPT_ECHO)
+ elsif OPT_SGA[0] == $1[1]
+ @telnet_option["SGA"] = false
+ self.write(IAC + DONT + OPT_SGA)
+ else
+ self.write(IAC + DONT + $1[1..1])
+ end
+ ''
+ elsif SB[0] == $1[0] # respond to "IAC SB xxx IAC SE"
+ if OPT_STARTTLS[0] == $1[1] && TLS_FOLLOWS[0] == $2[0]
+ @sock = OpenSSL::SSL::SSLSocket.new(@sock)
+ @sock.cert = @options['Cert'] unless @sock.cert
+ @sock.key = @options['Key'] unless @sock.key
+ @sock.ca_cert = @options['CACert']
+ @sock.ca_file = @options['CAFile']
+ @sock.ca_path = @options['CAPath']
+ @sock.timeout = @options['Timeout']
+ @sock.verify_mode = @options['VerifyMode']
+ @sock.verify_callback = @options['VerifyCallback']
+ @sock.verify_depth = @options['VerifyDepth']
+ @sock.connect
+ @ssl = true
+ end
+ ''
+ else
+ ''
+ end
+ end
+ end # preprocess
+
+ alias waitfor_org waitfor
+
+ def waitfor(options)
+ time_out = @options["Timeout"]
+ waittime = @options["Waittime"]
+
+ if options.kind_of?(Hash)
+ prompt = if options.has_key?("Match")
+ options["Match"]
+ elsif options.has_key?("Prompt")
+ options["Prompt"]
+ elsif options.has_key?("String")
+ Regexp.new( Regexp.quote(options["String"]) )
+ end
+ time_out = options["Timeout"] if options.has_key?("Timeout")
+ waittime = options["Waittime"] if options.has_key?("Waittime")
+ else
+ prompt = options
+ end
+
+ if time_out == false
+ time_out = nil
+ end
+
+ line = ''
+ buf = ''
+ @rest = '' unless @rest
+
+ until(prompt === line and not IO::select([@sock], nil, nil, waittime))
+ unless IO::select([@sock], nil, nil, time_out)
+ raise TimeoutError, "timed-out; wait for the next data"
+ end
+ begin
+ c = @rest + @sock.sysread(1024 * 1024)
+ @dumplog.log_dump('<', c) if @options.has_key?("Dump_log")
+ if @options["Telnetmode"]
+ pos = 0
+ catch(:next){
+ while true
+ case c[pos]
+ when IAC[0]
+ case c[pos+1]
+ when DO[0], DONT[0], WILL[0], WONT[0]
+ throw :next unless c[pos+2]
+ pos += 3
+ when SB[0]
+ ret = detect_sub_negotiation(c, pos)
+ throw :next unless ret
+ pos = ret
+ when nil
+ throw :next
+ else
+ pos += 2
+ end
+ when nil
+ throw :next
+ else
+ pos += 1
+ end
+ end
+ }
+
+ buf = preprocess(c[0...pos])
+ @rest = c[pos..-1]
+ end
+ @log.print(buf) if @options.has_key?("Output_log")
+ line.concat(buf)
+ yield buf if block_given?
+ rescue EOFError # End of file reached
+ if line == ''
+ line = nil
+ yield nil if block_given?
+ end
+ break
+ end
+ end
+ line
+ end
+
+ private
+
+ def detect_sub_negotiation(data, pos)
+ return nil if data.length < pos+6 # IAC SB x param IAC SE
+ pos += 3
+ while true
+ case data[pos]
+ when IAC[0]
+ if data[pos+1] == SE[0]
+ pos += 2
+ return pos
+ else
+ pos += 2
+ end
+ when nil
+ return nil
+ else
+ pos += 1
+ end
+ end
+ end
+
+ end
+end
diff --git a/ruby_1_8_5/ext/openssl/lib/openssl.rb b/ruby_1_8_5/ext/openssl/lib/openssl.rb
new file mode 100644
index 0000000000..58fd3887e3
--- /dev/null
+++ b/ruby_1_8_5/ext/openssl/lib/openssl.rb
@@ -0,0 +1,24 @@
+=begin
+= $RCSfile: openssl.rb,v $ -- Loader for all OpenSSL C-space and Ruby-space definitions
+
+= Info
+ 'OpenSSL for Ruby 2' project
+ Copyright (C) 2002 Michal Rokos <m.rokos@sh.cvut.cz>
+ All rights reserved.
+
+= Licence
+ This program is licenced under the same licence as Ruby.
+ (See the file 'LICENCE'.)
+
+= Version
+ $Id: openssl.rb,v 1.1 2003/07/23 16:11:29 gotoyuzo Exp $
+=end
+
+require 'openssl.so'
+
+require 'openssl/bn'
+require 'openssl/cipher'
+require 'openssl/digest'
+require 'openssl/ssl'
+require 'openssl/x509'
+
diff --git a/ruby_1_8_5/ext/openssl/lib/openssl/bn.rb b/ruby_1_8_5/ext/openssl/lib/openssl/bn.rb
new file mode 100644
index 0000000000..4a1595c7ab
--- /dev/null
+++ b/ruby_1_8_5/ext/openssl/lib/openssl/bn.rb
@@ -0,0 +1,35 @@
+=begin
+= $RCSfile: bn.rb,v $ -- Ruby-space definitions that completes C-space funcs for BN
+
+= Info
+ 'OpenSSL for Ruby 2' project
+ Copyright (C) 2002 Michal Rokos <m.rokos@sh.cvut.cz>
+ All rights reserved.
+
+= Licence
+ This program is licenced under the same licence as Ruby.
+ (See the file 'LICENCE'.)
+
+= Version
+ $Id: bn.rb,v 1.1 2003/07/23 16:11:30 gotoyuzo Exp $
+=end
+
+##
+# Should we care what if somebody require this file directly?
+#require 'openssl'
+
+module OpenSSL
+ class BN
+ include Comparable
+ end # BN
+end # OpenSSL
+
+##
+# Add double dispatch to Integer
+#
+class Integer
+ def to_bn
+ OpenSSL::BN::new(self)
+ end
+end # Integer
+
diff --git a/ruby_1_8_5/ext/openssl/lib/openssl/buffering.rb b/ruby_1_8_5/ext/openssl/lib/openssl/buffering.rb
new file mode 100644
index 0000000000..9eeb19d959
--- /dev/null
+++ b/ruby_1_8_5/ext/openssl/lib/openssl/buffering.rb
@@ -0,0 +1,239 @@
+=begin
+= $RCSfile: buffering.rb,v $ -- Buffering mix-in module.
+
+= Info
+ 'OpenSSL for Ruby 2' project
+ Copyright (C) 2001 GOTOU YUUZOU <gotoyuzo@notwork.org>
+ All rights reserved.
+
+= Licence
+ This program is licenced under the same licence as Ruby.
+ (See the file 'LICENCE'.)
+
+= Version
+ $Id: buffering.rb,v 1.5.2.4 2005/09/04 22:03:24 gotoyuzo Exp $
+=end
+
+module Buffering
+ include Enumerable
+ attr_accessor :sync
+ BLOCK_SIZE = 1024*16
+
+ def initialize(*args)
+ @eof = false
+ @rbuffer = ""
+ @sync = @io.sync
+ end
+
+ #
+ # for reading.
+ #
+ private
+
+ def fill_rbuff
+ begin
+ @rbuffer << self.sysread(BLOCK_SIZE)
+ rescue Errno::EAGAIN
+ retry
+ rescue EOFError
+ @eof = true
+ end
+ end
+
+ def consume_rbuff(size=nil)
+ if @rbuffer.empty?
+ nil
+ else
+ size = @rbuffer.size unless size
+ ret = @rbuffer[0, size]
+ @rbuffer[0, size] = ""
+ ret
+ end
+ end
+
+ public
+
+ def read(size=nil, buf=nil)
+ if size == 0
+ if buf
+ buf.clear
+ else
+ buf = ""
+ end
+ return @eof ? nil : buf
+ end
+ until @eof
+ break if size && size <= @rbuffer.size
+ fill_rbuff
+ end
+ ret = consume_rbuff(size) || ""
+ if buf
+ buf.replace(ret)
+ ret = buf
+ end
+ (size && ret.empty?) ? nil : ret
+ end
+
+ def readpartial(maxlen, buf=nil)
+ if maxlen == 0
+ if buf
+ buf.clear
+ else
+ buf = ""
+ end
+ return @eof ? nil : buf
+ end
+ if @rbuffer.empty?
+ begin
+ return sysread(maxlen, buf)
+ rescue Errno::EAGAIN
+ retry
+ end
+ end
+ ret = consume_rbuff(maxlen)
+ if buf
+ buf.replace(ret)
+ ret = buf
+ end
+ raise EOFError if ret.empty?
+ ret
+ end
+
+ def gets(eol=$/)
+ idx = @rbuffer.index(eol)
+ until @eof
+ break if idx
+ fill_rbuff
+ idx = @rbuffer.index(eol)
+ end
+ if eol.is_a?(Regexp)
+ size = idx ? idx+$&.size : nil
+ else
+ size = idx ? idx+eol.size : nil
+ end
+ consume_rbuff(size)
+ end
+
+ def each(eol=$/)
+ while line = self.gets(eol)
+ yield line
+ end
+ end
+ alias each_line each
+
+ def readlines(eol=$/)
+ ary = []
+ while line = self.gets(eol)
+ ary << line
+ end
+ ary
+ end
+
+ def readline(eol=$/)
+ raise EOFError if eof?
+ gets(eol)
+ end
+
+ def getc
+ c = read(1)
+ c ? c[0] : nil
+ end
+
+ def each_byte
+ while c = getc
+ yield(c)
+ end
+ end
+
+ def readchar
+ raise EOFError if eof?
+ getc
+ end
+
+ def ungetc(c)
+ @rbuffer[0,0] = c.chr
+ end
+
+ def eof?
+ fill_rbuff if !@eof && @rbuffer.empty?
+ @eof && @rbuffer.empty?
+ end
+ alias eof eof?
+
+ #
+ # for writing.
+ #
+ private
+
+ def do_write(s)
+ @wbuffer = "" unless defined? @wbuffer
+ @wbuffer << s
+ @sync ||= false
+ if @sync or @wbuffer.size > BLOCK_SIZE or idx = @wbuffer.rindex($/)
+ remain = idx ? idx + $/.size : @wbuffer.length
+ nwritten = 0
+ while remain > 0
+ str = @wbuffer[nwritten,remain]
+ begin
+ nwrote = syswrite(str)
+ rescue Errno::EAGAIN
+ retry
+ end
+ remain -= nwrote
+ nwritten += nwrote
+ end
+ @wbuffer[0,nwritten] = ""
+ end
+ end
+
+ public
+
+ def write(s)
+ do_write(s)
+ s.length
+ end
+
+ def << (s)
+ do_write(s)
+ self
+ end
+
+ def puts(*args)
+ s = ""
+ if args.empty?
+ s << "\n"
+ end
+ args.each{|arg|
+ s << arg.to_s
+ if $/ && /\n\z/ !~ s
+ s << "\n"
+ end
+ }
+ do_write(s)
+ nil
+ end
+
+ def print(*args)
+ s = ""
+ args.each{ |arg| s << arg.to_s }
+ do_write(s)
+ nil
+ end
+
+ def printf(s, *args)
+ do_write(s % args)
+ nil
+ end
+
+ def flush
+ osync = @sync
+ @sync = true
+ do_write ""
+ @sync = osync
+ end
+
+ def close
+ flush rescue nil
+ sysclose
+ end
+end
diff --git a/ruby_1_8_5/ext/openssl/lib/openssl/cipher.rb b/ruby_1_8_5/ext/openssl/lib/openssl/cipher.rb
new file mode 100644
index 0000000000..7825e5e9e6
--- /dev/null
+++ b/ruby_1_8_5/ext/openssl/lib/openssl/cipher.rb
@@ -0,0 +1,58 @@
+=begin
+= $RCSfile: cipher.rb,v $ -- Ruby-space predefined Cipher subclasses
+
+= Info
+ 'OpenSSL for Ruby 2' project
+ Copyright (C) 2002 Michal Rokos <m.rokos@sh.cvut.cz>
+ All rights reserved.
+
+= Licence
+ This program is licenced under the same licence as Ruby.
+ (See the file 'LICENCE'.)
+
+= Version
+ $Id: cipher.rb,v 1.1.2.2 2006/06/20 11:18:15 gotoyuzo Exp $
+=end
+
+##
+# Should we care what if somebody require this file directly?
+#require 'openssl'
+
+module OpenSSL
+ module Cipher
+ %w(AES CAST5 BF DES IDEA RC2 RC4 RC5).each{|name|
+ klass = Class.new(Cipher){
+ define_method(:initialize){|*args|
+ cipher_name = args.inject(name){|n, arg| "#{n}-#{arg}" }
+ super(cipher_name)
+ }
+ }
+ const_set(name, klass)
+ }
+
+ %w(128 192 256).each{|keylen|
+ klass = Class.new(Cipher){
+ define_method(:initialize){|mode|
+ mode ||= "CBC"
+ cipher_name = "AES-#{keylen}-#{mode}"
+ super(cipher_name)
+ }
+ }
+ const_set("AES#{keylen}", klass)
+ }
+
+ class Cipher
+ def random_key
+ str = OpenSSL::Random.random_bytes(self.key_len)
+ self.key = str
+ return str
+ end
+
+ def random_iv
+ str = OpenSSL::Random.random_bytes(self.iv_len)
+ self.iv = str
+ return str
+ end
+ end
+ end # Cipher
+end # OpenSSL
diff --git a/ruby_1_8_5/ext/openssl/lib/openssl/digest.rb b/ruby_1_8_5/ext/openssl/lib/openssl/digest.rb
new file mode 100644
index 0000000000..6f2c998ff6
--- /dev/null
+++ b/ruby_1_8_5/ext/openssl/lib/openssl/digest.rb
@@ -0,0 +1,49 @@
+=begin
+= $RCSfile: digest.rb,v $ -- Ruby-space predefined Digest subclasses
+
+= Info
+ 'OpenSSL for Ruby 2' project
+ Copyright (C) 2002 Michal Rokos <m.rokos@sh.cvut.cz>
+ All rights reserved.
+
+= Licence
+ This program is licenced under the same licence as Ruby.
+ (See the file 'LICENCE'.)
+
+= Version
+ $Id: digest.rb,v 1.1.2.2 2006/06/20 11:18:15 gotoyuzo Exp $
+=end
+
+##
+# Should we care what if somebody require this file directly?
+#require 'openssl'
+
+module OpenSSL
+ module Digest
+
+ alg = %w(DSS DSS1 MD2 MD4 MD5 MDC2 RIPEMD160 SHA SHA1)
+ if OPENSSL_VERSION_NUMBER > 0x00908000
+ alg += %w(SHA224 SHA256 SHA384 SHA512)
+ end
+
+ alg.each{|name|
+ klass = Class.new(Digest){
+ define_method(:initialize){|*data|
+ if data.length > 1
+ raise ArgumentError,
+ "wrong number of arguments (#{data.length} for 1)"
+ end
+ super(name, data.first)
+ }
+ }
+ singleton = (class <<klass; self; end)
+ singleton.class_eval{
+ define_method(:digest){|data| Digest.digest(name, data) }
+ define_method(:hexdigest){|data| Digest.hexdigest(name, data) }
+ }
+ const_set(name, klass)
+ }
+
+ end # Digest
+end # OpenSSL
+
diff --git a/ruby_1_8_5/ext/openssl/lib/openssl/ssl.rb b/ruby_1_8_5/ext/openssl/lib/openssl/ssl.rb
new file mode 100644
index 0000000000..abef21d823
--- /dev/null
+++ b/ruby_1_8_5/ext/openssl/lib/openssl/ssl.rb
@@ -0,0 +1,135 @@
+=begin
+= $RCSfile: ssl.rb,v $ -- Ruby-space definitions that completes C-space funcs for SSL
+
+= Info
+ 'OpenSSL for Ruby 2' project
+ Copyright (C) 2001 GOTOU YUUZOU <gotoyuzo@notwork.org>
+ All rights reserved.
+
+= Licence
+ This program is licenced under the same licence as Ruby.
+ (See the file 'LICENCE'.)
+
+= Version
+ $Id: ssl.rb,v 1.5.2.6 2006/05/23 18:14:05 gotoyuzo Exp $
+=end
+
+require "openssl"
+require "openssl/buffering"
+require "fcntl"
+
+module OpenSSL
+ module SSL
+ module SocketForwarder
+ def addr
+ to_io.addr
+ end
+
+ def peeraddr
+ to_io.peeraddr
+ end
+
+ def setsockopt(level, optname, optval)
+ to_io.setsockopt(level, optname, optval)
+ end
+
+ def getsockopt(level, optname)
+ to_io.getsockopt(level, optname)
+ end
+
+ def fcntl(*args)
+ to_io.fcntl(*args)
+ end
+
+ def closed?
+ to_io.closed?
+ end
+
+ def do_not_reverse_lookup=(flag)
+ to_io.do_not_reverse_lookup = flag
+ end
+ end
+
+ module Nonblock
+ def initialize(*args)
+ flag = File::NONBLOCK
+ flag |= @io.fcntl(Fcntl::F_GETFL) if defined?(Fcntl::F_GETFL)
+ @io.fcntl(Fcntl::F_SETFL, flag)
+ super
+ end
+ end
+
+ class SSLSocket
+ include Buffering
+ include SocketForwarder
+ include Nonblock
+
+ def post_connection_check(hostname)
+ check_common_name = true
+ cert = peer_cert
+ cert.extensions.each{|ext|
+ next if ext.oid != "subjectAltName"
+ ext.value.split(/,\s+/).each{|general_name|
+ if /\ADNS:(.*)/ =~ general_name
+ check_common_name = false
+ reg = Regexp.escape($1).gsub(/\\\*/, "[^.]+")
+ return true if /\A#{reg}\z/i =~ hostname
+ elsif /\AIP Address:(.*)/ =~ general_name
+ check_common_name = false
+ return true if $1 == hostname
+ end
+ }
+ }
+ if check_common_name
+ cert.subject.to_a.each{|oid, value|
+ if oid == "CN"
+ reg = Regexp.escape(value).gsub(/\\\*/, "[^.]+")
+ return true if /\A#{reg}\z/i =~ hostname
+ end
+ }
+ end
+ raise SSLError, "hostname not match"
+ end
+ end
+
+ class SSLServer
+ include SocketForwarder
+ attr_accessor :start_immediately
+
+ def initialize(svr, ctx)
+ @svr = svr
+ @ctx = ctx
+ unless ctx.session_id_context
+ session_id = OpenSSL::Digest::MD5.hexdigest($0)
+ @ctx.session_id_context = session_id
+ end
+ @start_immediately = true
+ end
+
+ def to_io
+ @svr
+ end
+
+ def listen(backlog=5)
+ @svr.listen(backlog)
+ end
+
+ def accept
+ sock = @svr.accept
+ begin
+ ssl = OpenSSL::SSL::SSLSocket.new(sock, @ctx)
+ ssl.sync_close = true
+ ssl.accept if @start_immediately
+ ssl
+ rescue SSLError => ex
+ sock.close
+ raise ex
+ end
+ end
+
+ def close
+ @svr.close
+ end
+ end
+ end
+end
diff --git a/ruby_1_8_5/ext/openssl/lib/openssl/x509.rb b/ruby_1_8_5/ext/openssl/lib/openssl/x509.rb
new file mode 100644
index 0000000000..2ad3f8e96e
--- /dev/null
+++ b/ruby_1_8_5/ext/openssl/lib/openssl/x509.rb
@@ -0,0 +1,154 @@
+=begin
+= $RCSfile: x509.rb,v $ -- Ruby-space definitions that completes C-space funcs for X509 and subclasses
+
+= Info
+ 'OpenSSL for Ruby 2' project
+ Copyright (C) 2002 Michal Rokos <m.rokos@sh.cvut.cz>
+ All rights reserved.
+
+= Licence
+ This program is licenced under the same licence as Ruby.
+ (See the file 'LICENCE'.)
+
+= Version
+ $Id: x509.rb,v 1.4.2.2 2004/12/19 08:28:33 gotoyuzo Exp $
+=end
+
+require "openssl"
+
+module OpenSSL
+ module X509
+ class ExtensionFactory
+ def create_extension(*arg)
+ if arg.size > 1
+ create_ext(*arg)
+ else
+ send("create_ext_from_"+arg[0].class.name.downcase, arg[0])
+ end
+ end
+
+ 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"
+ oid, value = str.split(/=/, 2)
+ oid.strip!
+ value.strip!
+ create_ext(oid, value)
+ end
+
+ def create_ext_from_hash(hash)
+ create_ext(hash["oid"], hash["value"], hash["critical"])
+ end
+ end
+
+ class Extension
+ def to_s # "oid = critical, value"
+ str = self.oid
+ str << " = "
+ str << "critical, " if self.critical?
+ str << self.value.gsub(/\n/, ", ")
+ end
+
+ def to_h # {"oid"=>sn|ln, "value"=>value, "critical"=>true|false}
+ {"oid"=>self.oid,"value"=>self.value,"critical"=>self.critical?}
+ end
+
+ def to_a
+ [ self.oid, self.value, self.critical? ]
+ end
+ end
+
+ class Name
+ module RFC2253DN
+ Special = ',=+<>#;'
+ HexChar = /[0-9a-fA-F]/
+ HexPair = /#{HexChar}#{HexChar}/
+ HexString = /#{HexPair}+/
+ Pair = /\\(?:[#{Special}]|\\|"|#{HexPair})/
+ StringChar = /[^#{Special}\\"]/
+ QuoteChar = /[^\\"]/
+ AttributeType = /[a-zA-Z][0-9a-zA-Z]*|[0-9]+(?:\.[0-9]+)*/
+ AttributeValue = /
+ (?!["#])((?:#{StringChar}|#{Pair})*)|
+ \#(#{HexString})|
+ "((?:#{QuoteChar}|#{Pair})*)"
+ /x
+ TypeAndValue = /\A(#{AttributeType})=#{AttributeValue}/
+
+ module_function
+
+ def expand_pair(str)
+ return nil unless str
+ return str.gsub(Pair){|pair|
+ case pair.size
+ when 2 then pair[1,1]
+ when 3 then Integer("0x#{pair[1,2]}").chr
+ else raise OpenSSL::X509::NameError, "invalid pair: #{str}"
+ end
+ }
+ end
+
+ def expand_hexstring(str)
+ return nil unless str
+ der = str.gsub(HexPair){|hex| Integer("0x#{hex}").chr }
+ a1 = OpenSSL::ASN1.decode(der)
+ return a1.value, a1.tag
+ end
+
+ def expand_value(str1, str2, str3)
+ value = expand_pair(str1)
+ value, tag = expand_hexstring(str2) unless value
+ value = expand_pair(str3) unless value
+ return value, tag
+ end
+
+ def scan(dn)
+ str = dn
+ ary = []
+ while true
+ if md = TypeAndValue.match(str)
+ matched = md.to_s
+ remain = md.post_match
+ type = md[1]
+ value, tag = expand_value(md[2], md[3], md[4]) rescue nil
+ if value
+ type_and_value = [type, value]
+ type_and_value.push(tag) if tag
+ ary.unshift(type_and_value)
+ if remain.length > 2 && remain[0] == ?,
+ str = remain[1..-1]
+ next
+ elsif remain.length > 2 && remain[0] == ?+
+ raise OpenSSL::X509::NameError,
+ "multi-valued RDN is not supported: #{dn}"
+ elsif remain.empty?
+ break
+ end
+ end
+ end
+ msg_dn = dn[0, dn.length - str.length] + " =>" + str
+ raise OpenSSL::X509::NameError, "malformed RDN: #{msg_dn}"
+ end
+ return ary
+ end
+ end
+
+ class <<self
+ def parse_rfc2253(str, template=OBJECT_TYPE_TEMPLATE)
+ ary = OpenSSL::X509::Name::RFC2253DN.scan(str)
+ self.new(ary, template)
+ end
+
+ def parse_openssl(str, template=OBJECT_TYPE_TEMPLATE)
+ ary = str.scan(/\s*([^\/,]+)\s*/).collect{|i| i[0].split("=", 2) }
+ self.new(ary, template)
+ end
+
+ alias parse parse_openssl
+ end
+ end
+ end
+end
diff --git a/ruby_1_8_5/ext/openssl/openssl_missing.c b/ruby_1_8_5/ext/openssl/openssl_missing.c
new file mode 100644
index 0000000000..2c005f41e5
--- /dev/null
+++ b/ruby_1_8_5/ext/openssl/openssl_missing.c
@@ -0,0 +1,345 @@
+/*
+ * $Id: openssl_missing.c,v 1.2.2.4 2006/06/02 10:02:56 gotoyuzo Exp $
+ * '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'.)
+ */
+#include RUBY_EXTCONF_H
+
+#if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ST_ENGINE)
+# include <openssl/engine.h>
+#endif
+#include <openssl/x509_vfy.h>
+
+#if !defined(OPENSSL_NO_HMAC)
+#include <string.h> /* memcpy() */
+#include <openssl/hmac.h>
+
+#include "openssl_missing.h"
+
+#if !defined(HAVE_HMAC_CTX_COPY)
+int
+HMAC_CTX_copy(HMAC_CTX *out, HMAC_CTX *in)
+{
+ if (!out || !in) return 0;
+ memcpy(out, in, sizeof(HMAC_CTX));
+
+ if (!EVP_MD_CTX_copy(&out->md_ctx, &in->md_ctx)
+ || !EVP_MD_CTX_copy(&out->i_ctx, &in->i_ctx)
+ || !EVP_MD_CTX_copy(&out->o_ctx, &in->o_ctx))
+ return 0;
+ return 1;
+}
+#endif /* HAVE_HMAC_CTX_COPY */
+#endif /* NO_HMAC */
+
+#if !defined(HAVE_X509_STORE_SET_EX_DATA)
+
+int X509_STORE_set_ex_data(X509_STORE *str, int idx, void *data)
+{
+ return CRYPTO_set_ex_data(&str->ex_data, idx, data);
+}
+
+void *X509_STORE_get_ex_data(X509_STORE *str, int idx)
+{
+ return CRYPTO_get_ex_data(&str->ex_data, idx);
+}
+#endif
+
+#if !defined(HAVE_EVP_MD_CTX_CREATE)
+EVP_MD_CTX *
+EVP_MD_CTX_create(void)
+{
+ EVP_MD_CTX *ctx = OPENSSL_malloc(sizeof(EVP_MD_CTX));
+ if (!ctx) return NULL;
+
+ memset(ctx, 0, sizeof(EVP_MD_CTX));
+
+ return ctx;
+}
+#endif
+
+#if !defined(HAVE_EVP_MD_CTX_CLEANUP)
+int
+EVP_MD_CTX_cleanup(EVP_MD_CTX *ctx)
+{
+ /* FIXME!!! */
+ memset(ctx, 0, sizeof(EVP_MD_CTX));
+
+ return 1;
+}
+#endif
+
+#if !defined(HAVE_EVP_MD_CTX_DESTROY)
+void
+EVP_MD_CTX_destroy(EVP_MD_CTX *ctx)
+{
+ EVP_MD_CTX_cleanup(ctx);
+ OPENSSL_free(ctx);
+}
+#endif
+
+#if !defined(HAVE_EVP_MD_CTX_INIT)
+void
+EVP_MD_CTX_init(EVP_MD_CTX *ctx)
+{
+ memset(ctx, 0, sizeof(EVP_MD_CTX));
+}
+#endif
+
+#if !defined(HAVE_HMAC_CTX_INIT)
+void
+HMAC_CTX_init(HMAC_CTX *ctx)
+{
+ EVP_MD_CTX_init(&ctx->i_ctx);
+ EVP_MD_CTX_init(&ctx->o_ctx);
+ EVP_MD_CTX_init(&ctx->md_ctx);
+}
+#endif
+
+#if !defined(HAVE_HMAC_CTX_CLEANUP)
+void
+HMAC_CTX_cleanup(HMAC_CTX *ctx)
+{
+ EVP_MD_CTX_cleanup(&ctx->i_ctx);
+ EVP_MD_CTX_cleanup(&ctx->o_ctx);
+ EVP_MD_CTX_cleanup(&ctx->md_ctx);
+ memset(ctx, 0, sizeof(HMAC_CTX));
+}
+#endif
+
+#if !defined(HAVE_EVP_CIPHER_CTX_COPY)
+/*
+ * this function does not exist in OpenSSL yet... or ever?.
+ * a future version may break this function.
+ * tested on 0.9.7d.
+ */
+int
+EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, EVP_CIPHER_CTX *in)
+{
+ memcpy(out, in, sizeof(EVP_CIPHER_CTX));
+
+#if defined(HAVE_ENGINE_ADD) && defined(HAVE_ST_ENGINE)
+ if (in->engine) ENGINE_add(out->engine);
+ if (in->cipher_data) {
+ out->cipher_data = OPENSSL_malloc(in->cipher->ctx_size);
+ memcpy(out->cipher_data, in->cipher_data, in->cipher->ctx_size);
+ }
+#endif
+
+ return 1;
+}
+#endif
+
+#if !defined(HAVE_X509_CRL_SET_VERSION)
+int
+X509_CRL_set_version(X509_CRL *x, long version)
+{
+ if (x == NULL || x->crl == NULL) return 0;
+ if (x->crl->version == NULL) {
+ x->crl->version = M_ASN1_INTEGER_new();
+ if (x->crl->version == NULL) return 0;
+ }
+ return ASN1_INTEGER_set(x->crl->version, version);
+}
+#endif
+
+#if !defined(HAVE_X509_CRL_SET_ISSUER_NAME)
+int
+X509_CRL_set_issuer_name(X509_CRL *x, X509_NAME *name)
+{
+ if (x == NULL || x->crl == NULL) return 0;
+ return X509_NAME_set(&x->crl->issuer, name);
+}
+#endif
+
+#if !defined(HAVE_X509_CRL_SORT)
+int
+X509_CRL_sort(X509_CRL *c)
+{
+ int i;
+ X509_REVOKED *r;
+ /* sort the data so it will be written in serial
+ * number order */
+ sk_X509_REVOKED_sort(c->crl->revoked);
+ for (i=0; i<sk_X509_REVOKED_num(c->crl->revoked); i++) {
+ r=sk_X509_REVOKED_value(c->crl->revoked, i);
+ r->sequence=i;
+ }
+ return 1;
+}
+#endif
+
+#if !defined(HAVE_X509_CRL_ADD0_REVOKED)
+static int
+OSSL_X509_REVOKED_cmp(const X509_REVOKED * const *a, const X509_REVOKED * const *b)
+{
+ return(ASN1_STRING_cmp(
+ (ASN1_STRING *)(*a)->serialNumber,
+ (ASN1_STRING *)(*b)->serialNumber));
+}
+
+int
+X509_CRL_add0_revoked(X509_CRL *crl, X509_REVOKED *rev)
+{
+ X509_CRL_INFO *inf;
+
+ inf = crl->crl;
+ if (!inf->revoked)
+ inf->revoked = sk_X509_REVOKED_new(OSSL_X509_REVOKED_cmp);
+ if (!inf->revoked || !sk_X509_REVOKED_push(inf->revoked, rev))
+ return 0;
+ return 1;
+}
+#endif
+
+#if !defined(HAVE_BN_MOD_SQR)
+int
+BN_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx)
+{
+ if (!BN_sqr(r, (BIGNUM*)a, ctx)) return 0;
+ return BN_mod(r, r, m, ctx);
+}
+#endif
+
+#if !defined(HAVE_BN_MOD_ADD) || !defined(HAVE_BN_MOD_SUB)
+int BN_nnmod(BIGNUM *r, const BIGNUM *m, const BIGNUM *d, BN_CTX *ctx)
+{
+ if (!BN_mod(r,m,d,ctx)) return 0;
+ if (!r->neg) return 1;
+ return (d->neg ? BN_sub : BN_add)(r, r, d);
+}
+#endif
+
+#if !defined(HAVE_BN_MOD_ADD)
+int
+BN_mod_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, BN_CTX *ctx)
+{
+ if (!BN_add(r, a, b)) return 0;
+ return BN_nnmod(r, r, m, ctx);
+}
+#endif
+
+#if !defined(HAVE_BN_MOD_SUB)
+int
+BN_mod_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, BN_CTX *ctx)
+{
+ if (!BN_sub(r, a, b)) return 0;
+ return BN_nnmod(r, r, m, ctx);
+}
+#endif
+
+#if !defined(HAVE_BN_RAND_RANGE) || !defined(HAVE_BN_PSEUDO_RAND_RANGE)
+static int
+bn_rand_range(int pseudo, BIGNUM *r, BIGNUM *range)
+{
+ int (*bn_rand)(BIGNUM *, int, int, int) = pseudo ? BN_pseudo_rand : BN_rand;
+ int n;
+
+ if (range->neg || BN_is_zero(range)) return 0;
+
+ n = BN_num_bits(range);
+
+ if (n == 1) {
+ if (!BN_zero(r)) return 0;
+ } else if (!BN_is_bit_set(range, n - 2) && !BN_is_bit_set(range, n - 3)) {
+ do {
+ if (!bn_rand(r, n + 1, -1, 0)) return 0;
+ if (BN_cmp(r ,range) >= 0) {
+ if (!BN_sub(r, r, range)) return 0;
+ if (BN_cmp(r, range) >= 0)
+ if (!BN_sub(r, r, range)) return 0;
+ }
+ } while (BN_cmp(r, range) >= 0);
+ } else {
+ do {
+ if (!bn_rand(r, n, -1, 0)) return 0;
+ } while (BN_cmp(r, range) >= 0);
+ }
+
+ return 1;
+}
+#endif
+
+#if !defined(HAVE_BN_RAND_RANGE)
+int
+BN_rand_range(BIGNUM *r, BIGNUM *range)
+{
+ return bn_rand_range(0, r, range);
+}
+#endif
+
+#if !defined(HAVE_BN_PSEUDO_RAND_RANGE)
+int
+BN_pseudo_rand_range(BIGNUM *r, BIGNUM *range)
+{
+ return bn_rand_range(1, r, range);
+}
+#endif
+
+#if !defined(HAVE_CONF_GET1_DEFAULT_CONFIG_FILE)
+#define OPENSSL_CONF "openssl.cnf"
+char *
+CONF_get1_default_config_file(void)
+{
+ char *file;
+ int len;
+
+ file = getenv("OPENSSL_CONF");
+ if (file) return BUF_strdup(file);
+ len = strlen(X509_get_default_cert_area());
+#ifndef OPENSSL_SYS_VMS
+ len++;
+#endif
+ len += strlen(OPENSSL_CONF);
+ file = OPENSSL_malloc(len + 1);
+ if (!file) return NULL;
+ strcpy(file,X509_get_default_cert_area());
+#ifndef OPENSSL_SYS_VMS
+ strcat(file,"/");
+#endif
+ strcat(file,OPENSSL_CONF);
+
+ return file;
+}
+#endif
+
+#if !defined(HAVE_PEM_DEF_CALLBACK)
+#define OSSL_PASS_MIN_LENGTH 4
+int
+PEM_def_callback(char *buf, int num, int w, void *key)
+{
+ int i,j;
+ const char *prompt;
+
+ if (key) {
+ i = strlen(key);
+ i = (i > num) ? num : i;
+ memcpy(buf, key, i);
+ return i;
+ }
+
+ prompt = EVP_get_pw_prompt();
+ if (prompt == NULL) prompt = "Enter PEM pass phrase:";
+ for (;;) {
+ i = EVP_read_pw_string(buf, num, prompt, w);
+ if (i != 0) {
+ memset(buf, 0, (unsigned int)num);
+ return(-1);
+ }
+ j = strlen(buf);
+ if (j < OSSL_PASS_MIN_LENGTH) {
+ fprintf(stderr,
+ "phrase is too short, needs to be at least %d chars\n",
+ OSSL_PASS_MIN_LENGTH);
+ }
+ else break;
+ }
+ return j;
+}
+#endif
+
diff --git a/ruby_1_8_5/ext/openssl/openssl_missing.h b/ruby_1_8_5/ext/openssl/openssl_missing.h
new file mode 100644
index 0000000000..8d580f5ee8
--- /dev/null
+++ b/ruby_1_8_5/ext/openssl/openssl_missing.h
@@ -0,0 +1,130 @@
+/*
+ * $Id: openssl_missing.h,v 1.2.2.2 2005/04/15 19:16:18 gotoyuzo Exp $
+ * '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_OPENSSL_MISSING_H_)
+#define _OSSL_OPENSSL_MISSING_H_
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/*
+ * These functions are not included in headers of OPENSSL <= 0.9.6b
+ */
+
+#if !defined(PEM_read_bio_DSAPublicKey)
+# define PEM_read_bio_DSAPublicKey(bp,x,cb,u) (DSA *)PEM_ASN1_read_bio( \
+ (char *(*)())d2i_DSAPublicKey,PEM_STRING_DSA_PUBLIC,bp,(char **)x,cb,u)
+#endif
+
+#if !defined(PEM_write_bio_DSAPublicKey)
+# define PEM_write_bio_DSAPublicKey(bp,x) \
+ PEM_ASN1_write_bio((int (*)())i2d_DSAPublicKey,\
+ PEM_STRING_DSA_PUBLIC,\
+ bp,(char *)x, NULL, NULL, 0, NULL, NULL)
+#endif
+
+#if !defined(DSAPrivateKey_dup)
+# define DSAPrivateKey_dup(dsa) (DSA *)ASN1_dup((int (*)())i2d_DSAPrivateKey, \
+ (char *(*)())d2i_DSAPrivateKey,(char *)dsa)
+#endif
+
+#if !defined(DSAPublicKey_dup)
+# define DSAPublicKey_dup(dsa) (DSA *)ASN1_dup((int (*)())i2d_DSAPublicKey, \
+ (char *(*)())d2i_DSAPublicKey,(char *)dsa)
+#endif
+
+#if !defined(X509_REVOKED_dup)
+# define X509_REVOKED_dup(rev) (X509_REVOKED *)ASN1_dup((int (*)())i2d_X509_REVOKED, \
+ (char *(*)())d2i_X509_REVOKED, (char *)rev)
+#endif
+
+#if !defined(PKCS7_SIGNER_INFO_dup)
+# define PKCS7_SIGNER_INFO_dup(si) (PKCS7_SIGNER_INFO *)ASN1_dup((int (*)())i2d_PKCS7_SIGNER_INFO, \
+ (char *(*)())d2i_PKCS7_SIGNER_INFO, (char *)si)
+#endif
+
+#if !defined(PKCS7_RECIP_INFO_dup)
+# define PKCS7_RECIP_INFO_dup(ri) (PKCS7_RECIP_INFO *)ASN1_dup((int (*)())i2d_PKCS7_RECIP_INFO, \
+ (char *(*)())d2i_PKCS7_RECIP_INFO, (char *)ri)
+#endif
+
+void HMAC_CTX_init(HMAC_CTX *ctx);
+int HMAC_CTX_copy(HMAC_CTX *out, HMAC_CTX *in);
+void HMAC_CTX_cleanup(HMAC_CTX *ctx);
+
+EVP_MD_CTX *EVP_MD_CTX_create(void);
+void EVP_MD_CTX_init(EVP_MD_CTX *ctx);
+int EVP_MD_CTX_cleanup(EVP_MD_CTX *ctx);
+void EVP_MD_CTX_destroy(EVP_MD_CTX *ctx);
+
+#if !defined(HAVE_EVP_CIPHER_CTX_COPY)
+int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, EVP_CIPHER_CTX *in);
+#endif
+
+#if !defined(HAVE_EVP_DIGESTINIT_EX)
+# define EVP_DigestInit_ex(ctx, md, engine) EVP_DigestInit(ctx, md)
+#endif
+#if !defined(HAVE_EVP_DIGESTFINAL_EX)
+# define EVP_DigestFinal_ex(ctx, buf, len) EVP_DigestFinal(ctx, buf, len)
+#endif
+
+#if !defined(HAVE_EVP_CIPHERINIT_EX)
+# define EVP_CipherInit_ex(ctx, type, impl, key, iv, enc) EVP_CipherInit(ctx, type, key, iv, enc)
+#endif
+#if !defined(HAVE_EVP_CIPHERFINAL_EX)
+# define EVP_CipherFinal_ex(ctx, outm, outl) EVP_CipherFinal(ctx, outm, outl)
+#endif
+
+#if !defined(EVP_CIPHER_name)
+# define EVP_CIPHER_name(e) OBJ_nid2sn(EVP_CIPHER_nid(e))
+#endif
+
+#if !defined(EVP_MD_name)
+# define EVP_MD_name(e) OBJ_nid2sn(EVP_MD_type(e))
+#endif
+
+#if !defined(HAVE_EVP_HMAC_INIT_EX)
+# define HMAC_Init_ex(ctx, key, len, digest, engine) HMAC_Init(ctx, key, len, digest)
+#endif
+
+#if !defined(PKCS7_is_detached)
+# define PKCS7_is_detached(p7) (PKCS7_type_is_signed(p7) && PKCS7_get_detached(p7))
+#endif
+
+#if !defined(PKCS7_type_is_encrypted)
+# define PKCS7_type_is_encrypted(a) (OBJ_obj2nid((a)->type) == NID_pkcs7_encrypted)
+#endif
+
+#if !defined(HAVE_OPENSSL_CLEANSE)
+#define OPENSSL_cleanse(p, l) memset(p, 0, l)
+#endif
+
+void *X509_STORE_get_ex_data(X509_STORE *str, int idx);
+int X509_STORE_set_ex_data(X509_STORE *str, int idx, void *data);
+int X509_CRL_set_version(X509_CRL *x, long version);
+int X509_CRL_set_issuer_name(X509_CRL *x, X509_NAME *name);
+int X509_CRL_sort(X509_CRL *c);
+int X509_CRL_add0_revoked(X509_CRL *crl, X509_REVOKED *rev);
+int BN_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx);
+int BN_mod_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, BN_CTX *ctx);
+int BN_mod_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, BN_CTX *ctx);
+int BN_rand_range(BIGNUM *r, BIGNUM *range);
+int BN_pseudo_rand_range(BIGNUM *r, BIGNUM *range);
+char *CONF_get1_default_config_file(void);
+int PEM_def_callback(char *buf, int num, int w, void *key);
+
+#if defined(__cplusplus)
+}
+#endif
+
+
+#endif /* _OSSL_OPENSSL_MISSING_H_ */
+
diff --git a/ruby_1_8_5/ext/openssl/ossl.c b/ruby_1_8_5/ext/openssl/ossl.c
new file mode 100644
index 0000000000..01c5ca2a04
--- /dev/null
+++ b/ruby_1_8_5/ext/openssl/ossl.c
@@ -0,0 +1,476 @@
+/*
+ * $Id: ossl.c,v 1.11.2.6 2005/11/01 01:52:13 gotoyuzo Exp $
+ * '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'.)
+ */
+#include "ossl.h"
+#include <stdarg.h> /* for ossl_raise */
+
+/*
+ * String to HEXString conversion
+ */
+int
+string2hex(char *buf, int buf_len, char **hexbuf, int *hexbuf_len)
+{
+ static const char hex[]="0123456789abcdef";
+ int i, len = 2 * buf_len;
+
+ if (buf_len < 0 || len < buf_len) { /* PARANOIA? */
+ return -1;
+ }
+ if (!hexbuf) { /* if no buf, return calculated len */
+ if (hexbuf_len) {
+ *hexbuf_len = len;
+ }
+ return len;
+ }
+ if (!(*hexbuf = OPENSSL_malloc(len + 1))) {
+ return -1;
+ }
+ for (i = 0; i < buf_len; i++) {
+ (*hexbuf)[2 * i] = hex[((unsigned char)buf[i]) >> 4];
+ (*hexbuf)[2 * i + 1] = hex[buf[i] & 0x0f];
+ }
+ (*hexbuf)[2 * i] = '\0';
+
+ if (hexbuf_len) {
+ *hexbuf_len = len;
+ }
+ return len;
+}
+
+/*
+ * Data Conversion
+ */
+STACK_OF(X509) *
+ossl_x509_ary2sk0(VALUE ary)
+{
+ STACK_OF(X509) *sk;
+ VALUE val;
+ X509 *x509;
+ int i;
+
+ Check_Type(ary, T_ARRAY);
+ sk = sk_X509_new_null();
+ if (!sk) ossl_raise(eOSSLError, NULL);
+
+ for (i = 0; i < RARRAY(ary)->len; i++) {
+ val = rb_ary_entry(ary, i);
+ if (!rb_obj_is_kind_of(val, cX509Cert)) {
+ sk_X509_pop_free(sk, X509_free);
+ ossl_raise(eOSSLError, "object not X509 cert in array");
+ }
+ x509 = DupX509CertPtr(val); /* NEED TO DUP */
+ sk_X509_push(sk, x509);
+ }
+ return sk;
+}
+
+STACK_OF(X509) *
+ossl_protect_x509_ary2sk(VALUE ary, int *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;
+}
+
+#define OSSL_IMPL_SK2ARY(name, type) \
+VALUE \
+ossl_##name##_sk2ary(STACK *sk) \
+{ \
+ type *t; \
+ int i, num; \
+ VALUE ary; \
+ \
+ if (!sk) { \
+ OSSL_Debug("empty sk!"); \
+ return Qnil; \
+ } \
+ num = sk_num(sk); \
+ if (num < 0) { \
+ OSSL_Debug("items in sk < -1???"); \
+ return rb_ary_new(); \
+ } \
+ ary = rb_ary_new2(num); \
+ \
+ for (i=0; i<num; i++) { \
+ t = (type *)sk_value(sk, i); \
+ rb_ary_push(ary, ossl_##name##_new(t)); \
+ } \
+ return ary; \
+}
+OSSL_IMPL_SK2ARY(x509, X509)
+OSSL_IMPL_SK2ARY(x509crl, X509_CRL)
+
+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(*)_((VALUE)))ossl_str_new, len, &status);
+ if(!NIL_P(str)) memcpy(RSTRING(str)->ptr, buf, len);
+ OPENSSL_free(buf);
+ if(status) rb_jump_tag(status);
+
+ return str;
+}
+
+/*
+ * our default PEM callback
+ */
+static VALUE
+ossl_pem_passwd_cb0(VALUE flag)
+{
+ VALUE pass;
+
+ pass = rb_yield(flag);
+ SafeStringValue(pass);
+
+ return pass;
+}
+
+int
+ossl_pem_passwd_cb(char *buf, int max_len, int flag, void *pwd)
+{
+ int len, status = 0;
+ VALUE rflag, pass;
+
+ if (pwd || !rb_block_given_p())
+ return PEM_def_callback(buf, max_len, flag, pwd);
+
+ while (1) {
+ /*
+ * when the flag is nonzero, this passphrase
+ * will be used to perform encryption; otherwise it will
+ * be used to perform decryption.
+ */
+ rflag = flag ? Qtrue : Qfalse;
+ pass = rb_protect(ossl_pem_passwd_cb0, rflag, &status);
+ if (status) return -1; /* exception was raised. */
+ len = RSTRING(pass)->len;
+ if (len < 4) { /* 4 is OpenSSL hardcoded limit */
+ rb_warning("password must be longer than 4 bytes");
+ continue;
+ }
+ if (len > max_len) {
+ rb_warning("password must be shorter then %d bytes", max_len-1);
+ continue;
+ }
+ memcpy(buf, RSTRING(pass)->ptr, len);
+ break;
+ }
+ return len;
+}
+
+/*
+ * Verify callback
+ */
+int ossl_verify_cb_idx;
+
+VALUE
+ossl_call_verify_cb_proc(struct ossl_verify_cb_args *args)
+{
+ return rb_funcall(args->proc, rb_intern("call"), 2,
+ args->preverify_ok, args->store_ctx);
+}
+
+int
+ossl_verify_cb(int ok, X509_STORE_CTX *ctx)
+{
+ VALUE proc, rctx, ret;
+ struct ossl_verify_cb_args args;
+ int state = 0;
+
+ proc = (VALUE)X509_STORE_CTX_get_ex_data(ctx, ossl_verify_cb_idx);
+ if ((void*)proc == 0)
+ proc = (VALUE)X509_STORE_get_ex_data(ctx->ctx, ossl_verify_cb_idx);
+ if ((void*)proc == 0)
+ return ok;
+ if (!NIL_P(proc)) {
+ rctx = rb_protect((VALUE(*)(VALUE))ossl_x509stctx_new,
+ (VALUE)ctx, &state);
+ ret = Qfalse;
+ if (!state) {
+ args.proc = proc;
+ args.preverify_ok = ok ? Qtrue : Qfalse;
+ args.store_ctx = rctx;
+ ret = rb_ensure(ossl_call_verify_cb_proc, (VALUE)&args,
+ ossl_x509stctx_clear_ptr, rctx);
+ }
+ if (ret == Qtrue) {
+ X509_STORE_CTX_set_error(ctx, X509_V_OK);
+ ok = 1;
+ }
+ else{
+ if (X509_STORE_CTX_get_error(ctx) == X509_V_OK) {
+ X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_REJECTED);
+ }
+ ok = 0;
+ }
+ }
+
+ return ok;
+}
+
+/*
+ * main module
+ */
+VALUE mOSSL;
+
+/*
+ * OpenSSLError < StandardError
+ */
+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
+ */
+void
+ossl_raise(VALUE exc, const char *fmt, ...)
+{
+ va_list args;
+ char buf[BUFSIZ];
+ const char *msg;
+ long e;
+ int len = 0;
+
+#ifdef HAVE_ERR_PEEK_LAST_ERROR
+ e = ERR_peek_last_error();
+#else
+ e = ERR_peek_error();
+#endif
+ if (fmt) {
+ va_start(args, fmt);
+ len = vsnprintf(buf, BUFSIZ, fmt, args);
+ va_end(args);
+ }
+ if (len < BUFSIZ && e) {
+ if (dOSSL == Qtrue) /* FULL INFO */
+ msg = ERR_error_string(e, NULL);
+ else
+ msg = ERR_reason_error_string(e);
+ fmt = len ? ": %s" : "%s";
+ len += snprintf(buf+len, BUFSIZ-len, fmt, msg);
+ }
+ if (dOSSL == Qtrue){ /* show all errors on the stack */
+ while ((e = ERR_get_error()) != 0){
+ rb_warn("error on stack: %s", ERR_error_string(e, NULL));
+ }
+ }
+ ERR_clear_error();
+
+ if(len > BUFSIZ) len = strlen(buf);
+ rb_exc_raise(rb_exc_new(exc, buf, len));
+}
+
+VALUE
+ossl_get_errors()
+{
+ VALUE ary;
+ long e;
+
+ ary = rb_ary_new();
+ while ((e = ERR_get_error()) != 0){
+ rb_ary_push(ary, rb_str_new2(ERR_error_string(e, NULL)));
+ }
+
+ return ary;
+}
+
+/*
+ * Debug
+ */
+VALUE dOSSL;
+
+#if !defined(HAVE_VA_ARGS_MACRO)
+void
+ossl_debug(const char *fmt, ...)
+{
+ va_list args;
+
+ if (dOSSL == Qtrue) {
+ fprintf(stderr, "OSSL_DEBUG: ");
+ va_start(args, fmt);
+ vfprintf(stderr, fmt, args);
+ va_end(args);
+ fprintf(stderr, " [CONTEXT N/A]\n");
+ }
+}
+#endif
+
+static VALUE
+ossl_debug_get(VALUE self)
+{
+ return dOSSL;
+}
+
+static VALUE
+ossl_debug_set(VALUE self, VALUE val)
+{
+ VALUE old = dOSSL;
+ dOSSL = val;
+
+ if (old != dOSSL) {
+ if (dOSSL == Qtrue) {
+ CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
+ fprintf(stderr, "OSSL_DEBUG: IS NOW ON!\n");
+ } else if (old == Qtrue) {
+ CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_OFF);
+ fprintf(stderr, "OSSL_DEBUG: IS NOW OFF!\n");
+ }
+ }
+ return val;
+}
+
+/*
+ * OSSL library init
+ */
+void
+Init_openssl()
+{
+ /*
+ * Init timezone info
+ */
+#if 0
+ tzset();
+#endif
+
+ /*
+ * Init all digests, ciphers
+ */
+ /* CRYPTO_malloc_init(); */
+ /* ENGINE_load_builtin_engines(); */
+ OpenSSL_add_ssl_algorithms();
+ OpenSSL_add_all_algorithms();
+ ERR_load_crypto_strings();
+ SSL_load_error_strings();
+
+ /*
+ * FIXME:
+ * On unload do:
+ */
+#if 0
+ CONF_modules_unload(1);
+ destroy_ui_method();
+ EVP_cleanup();
+ ENGINE_cleanup();
+ CRYPTO_cleanup_all_ex_data();
+ ERR_remove_state(0);
+ ERR_free_strings();
+#endif
+
+ /*
+ * Init main module
+ */
+ mOSSL = rb_define_module("OpenSSL");
+
+ /*
+ * Constants
+ */
+ rb_define_const(mOSSL, "VERSION", rb_str_new2(OSSL_VERSION));
+ rb_define_const(mOSSL, "OPENSSL_VERSION", rb_str_new2(OPENSSL_VERSION_TEXT));
+ rb_define_const(mOSSL, "OPENSSL_VERSION_NUMBER", INT2NUM(OPENSSL_VERSION_NUMBER));
+
+ /*
+ * Generic error,
+ * common for all classes under OpenSSL module
+ */
+ eOSSLError = rb_define_class_under(mOSSL,"OpenSSLError",rb_eStandardError);
+
+ /*
+ * Verify callback Proc index for ext-data
+ */
+ ossl_verify_cb_idx =
+ X509_STORE_CTX_get_ex_new_index(0, "ossl_verify_cb_idx", 0, 0, 0);
+
+ /*
+ * Init debug core
+ */
+ dOSSL = Qfalse;
+ rb_define_module_function(mOSSL, "debug", ossl_debug_get, 0);
+ rb_define_module_function(mOSSL, "debug=", ossl_debug_set, 1);
+ rb_define_module_function(mOSSL, "errors", ossl_get_errors, 0);
+
+ /*
+ * Get ID of to_der
+ */
+ ossl_s_to_der = rb_intern("to_der");
+
+ /*
+ * Init components
+ */
+ Init_ossl_bn();
+ Init_ossl_cipher();
+ Init_ossl_config();
+ Init_ossl_digest();
+ Init_ossl_hmac();
+ Init_ossl_ns_spki();
+ Init_ossl_pkcs12();
+ Init_ossl_pkcs7();
+ Init_ossl_pkey();
+ Init_ossl_rand();
+ Init_ossl_ssl();
+ Init_ossl_x509();
+ Init_ossl_ocsp();
+ Init_ossl_engine();
+ Init_ossl_asn1();
+}
+
+#if defined(OSSL_DEBUG)
+/*
+ * Check if all symbols are OK with 'make LDSHARED=gcc all'
+ */
+int
+main(int argc, char *argv[], char *env[])
+{
+ return 0;
+}
+#endif /* OSSL_DEBUG */
+
diff --git a/ruby_1_8_5/ext/openssl/ossl.h b/ruby_1_8_5/ext/openssl/ossl.h
new file mode 100644
index 0000000000..336b468eb2
--- /dev/null
+++ b/ruby_1_8_5/ext/openssl/ossl.h
@@ -0,0 +1,226 @@
+/*
+ * $Id: ossl.h,v 1.14.2.4.2.1 2006/12/25 11:16:49 shyouhei Exp $
+ * '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_H_)
+#define _OSSL_H_
+
+#include RUBY_EXTCONF_H
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/*
+ *_FILE_OFFSET_BITS needs to be defined before some system headers on
+ * Solaris.
+ */
+#include "config.h"
+
+/*
+ * Check the OpenSSL version
+ * The only supported are:
+ * OpenSSL >= 0.9.7
+ */
+#include <openssl/opensslv.h>
+
+#ifdef HAVE_ASSERT_H
+# include <assert.h>
+#else
+# define assert(condition)
+#endif
+
+#if defined(_WIN32)
+# define OpenFile WINAPI_OpenFile
+# define OSSL_NO_CONF_API 1
+#endif
+#include <errno.h>
+#include <openssl/err.h>
+#include <openssl/asn1_mac.h>
+#include <openssl/x509v3.h>
+#include <openssl/ssl.h>
+#include <openssl/pkcs12.h>
+#include <openssl/pkcs7.h>
+#include <openssl/hmac.h>
+#include <openssl/rand.h>
+#include <openssl/conf.h>
+#include <openssl/conf_api.h>
+#undef X509_NAME
+#undef PKCS7_SIGNER_INFO
+#if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ST_ENGINE)
+# define OSSL_ENGINE_ENABLED
+# include <openssl/engine.h>
+#endif
+#if defined(HAVE_OPENSSL_OCSP_H)
+# define OSSL_OCSP_ENABLED
+# include <openssl/ocsp.h>
+#endif
+#if defined(_WIN32)
+# undef OpenFile
+#endif
+
+/*
+ * OpenSSL has defined RFILE and Ruby has defined RFILE - so undef it!
+ */
+#if defined(RFILE) /*&& !defined(OSSL_DEBUG)*/
+# undef RFILE
+#endif
+#include <ruby.h>
+#include <rubyio.h>
+
+/*
+ * Common Module
+ */
+extern VALUE mOSSL;
+
+/*
+ * Common Error Class
+ */
+extern VALUE eOSSLError;
+
+/*
+ * CheckTypes
+ */
+#define OSSL_Check_Kind(obj, klass) do {\
+ if (!rb_obj_is_kind_of(obj, klass)) {\
+ ossl_raise(rb_eTypeError, "wrong argument (%s)! (Expected kind of %s)",\
+ rb_obj_classname(obj), rb_class2name(klass));\
+ }\
+} while (0)
+
+#define OSSL_Check_Instance(obj, klass) do {\
+ if (!rb_obj_is_instance_of(obj, klass)) {\
+ ossl_raise(rb_eTypeError, "wrong argument (%s)! (Expected instance of %s)",\
+ rb_obj_classname(obj), rb_class2name(klass));\
+ }\
+} while (0)
+
+#define OSSL_Check_Same_Class(obj1, obj2) do {\
+ if (!rb_obj_is_instance_of(obj1, rb_obj_class(obj2))) {\
+ ossl_raise(rb_eTypeError, "wrong argument type");\
+ }\
+} while (0)
+
+/*
+ * String to HEXString conversion
+ */
+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_x509_sk2ary(STACK_OF(X509) *certs);
+VALUE ossl_x509crl_sk2ary(STACK_OF(X509_CRL) *crl);
+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
+ */
+int ossl_pem_passwd_cb(char *, int, int, void *);
+
+/*
+ * ERRor messages
+ */
+#define OSSL_ErrMsg() ERR_reason_error_string(ERR_get_error())
+NORETURN(void ossl_raise(VALUE, const char *, ...));
+
+/*
+ * Verify callback
+ */
+extern int ossl_verify_cb_idx;
+
+struct ossl_verify_cb_args {
+ VALUE proc;
+ VALUE preverify_ok;
+ VALUE store_ctx;
+};
+
+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
+ */
+extern VALUE dOSSL;
+
+#if defined(HAVE_VA_ARGS_MACRO)
+#define OSSL_Debug(fmt, ...) do { \
+ if (dOSSL == Qtrue) { \
+ fprintf(stderr, "OSSL_DEBUG: "); \
+ fprintf(stderr, fmt, ##__VA_ARGS__); \
+ fprintf(stderr, " [%s:%d]\n", __FILE__, __LINE__); \
+ } \
+} while (0)
+
+#define OSSL_Warning(fmt, ...) do { \
+ OSSL_Debug(fmt, ##__VA_ARGS__); \
+ rb_warning(fmt, ##__VA_ARGS__); \
+} while (0)
+
+#define OSSL_Warn(fmt, ...) do { \
+ OSSL_Debug(fmt, ##__VA_ARGS__); \
+ rb_warn(fmt, ##__VA_ARGS__); \
+} while (0)
+#else
+void ossl_debug(const char *, ...);
+#define OSSL_Debug ossl_debug
+#define OSSL_Warning rb_warning
+#define OSSL_Warn rb_warn
+#endif
+
+/*
+ * Include all parts
+ */
+#include "openssl_missing.h"
+#include "ruby_missing.h"
+#include "ossl_asn1.h"
+#include "ossl_bio.h"
+#include "ossl_bn.h"
+#include "ossl_cipher.h"
+#include "ossl_config.h"
+#include "ossl_digest.h"
+#include "ossl_hmac.h"
+#include "ossl_ns_spki.h"
+#include "ossl_ocsp.h"
+#include "ossl_pkcs12.h"
+#include "ossl_pkcs7.h"
+#include "ossl_pkcs5.h"
+#include "ossl_pkey.h"
+#include "ossl_rand.h"
+#include "ossl_ssl.h"
+#include "ossl_version.h"
+#include "ossl_x509.h"
+#include "ossl_engine.h"
+
+void Init_openssl(void);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* _OSSL_H_ */
+
diff --git a/ruby_1_8_5/ext/openssl/ossl_asn1.c b/ruby_1_8_5/ext/openssl/ossl_asn1.c
new file mode 100644
index 0000000000..6bc5b88e8f
--- /dev/null
+++ b/ruby_1_8_5/ext/openssl/ossl_asn1.c
@@ -0,0 +1,1166 @@
+/*
+ * $Id: ossl_asn1.c,v 1.5.2.9 2006/04/29 13:52:15 gotoyuzo Exp $
+ * 'OpenSSL for Ruby' team members
+ * Copyright (C) 2003
+ * All rights reserved.
+ */
+/*
+ * This program is licenced under the same licence as Ruby.
+ * (See the file 'LICENCE'.)
+ */
+#include "ossl.h"
+
+#if defined(HAVE_SYS_TIME_H)
+# include <sys/time.h>
+#elif !defined(NT) && !defined(_WIN32)
+struct timeval {
+ long tv_sec; /* seconds */
+ long tv_usec; /* and microseconds */
+};
+#endif
+
+/*
+ * DATE conversion
+ */
+VALUE
+asn1time_to_time(ASN1_TIME *time)
+{
+ struct tm tm;
+ VALUE argv[6];
+
+ if (!time || !time->data) return Qnil;
+ memset(&tm, 0, sizeof(struct tm));
+
+ switch (time->type) {
+ case V_ASN1_UTCTIME:
+ if (sscanf(time->data, "%2d%2d%2d%2d%2d%2dZ", &tm.tm_year, &tm.tm_mon,
+ &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
+ ossl_raise(rb_eTypeError, "bad UTCTIME format");
+ }
+ if (tm.tm_year < 69) {
+ tm.tm_year += 2000;
+ } else {
+ tm.tm_year += 1900;
+ }
+ break;
+ case V_ASN1_GENERALIZEDTIME:
+ if (sscanf(time->data, "%4d%2d%2d%2d%2d%2dZ", &tm.tm_year, &tm.tm_mon,
+ &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
+ ossl_raise(rb_eTypeError, "bad GENERALIZEDTIME format" );
+ }
+ break;
+ default:
+ rb_warning("unknown time format");
+ return Qnil;
+ }
+ argv[0] = INT2NUM(tm.tm_year);
+ argv[1] = INT2NUM(tm.tm_mon);
+ argv[2] = INT2NUM(tm.tm_mday);
+ argv[3] = INT2NUM(tm.tm_hour);
+ argv[4] = INT2NUM(tm.tm_min);
+ argv[5] = INT2NUM(tm.tm_sec);
+
+ return rb_funcall2(rb_cTime, rb_intern("utc"), 6, argv);
+}
+
+/*
+ * This function is not exported in Ruby's *.h
+ */
+extern struct timeval rb_time_timeval(VALUE);
+
+time_t
+time_to_time_t(VALUE time)
+{
+ return (time_t)NUM2LONG(rb_Integer(time));
+}
+
+/*
+ * STRING conversion
+ */
+VALUE
+asn1str_to_str(ASN1_STRING *str)
+{
+ return rb_str_new(str->data, str->length);
+}
+
+/*
+ * ASN1_INTEGER conversions
+ * TODO: Make a decision what's the right way to do this.
+ */
+#define DO_IT_VIA_RUBY 0
+VALUE
+asn1integer_to_num(ASN1_INTEGER *ai)
+{
+ BIGNUM *bn;
+#if DO_IT_VIA_RUBY
+ char *txt;
+#endif
+ VALUE num;
+
+ if (!ai) {
+ ossl_raise(rb_eTypeError, "ASN1_INTEGER is NULL!");
+ }
+ if (!(bn = ASN1_INTEGER_to_BN(ai, NULL))) {
+ ossl_raise(eOSSLError, NULL);
+ }
+#if DO_IT_VIA_RUBY
+ if (!(txt = BN_bn2dec(bn))) {
+ BN_free(bn);
+ ossl_raise(eOSSLError, NULL);
+ }
+ num = rb_cstr_to_inum(txt, 10, Qtrue);
+ OPENSSL_free(txt);
+#else
+ num = ossl_bn_new(bn);
+#endif
+ BN_free(bn);
+
+ return num;
+}
+
+#if DO_IT_VIA_RUBY
+ASN1_INTEGER *
+num_to_asn1integer(VALUE obj, ASN1_INTEGER *ai)
+{
+ BIGNUM *bn = NULL;
+
+ if (RTEST(rb_obj_is_kind_of(obj, cBN))) {
+ bn = GetBNPtr(obj);
+ } else {
+ obj = rb_String(obj);
+ if (!BN_dec2bn(&bn, StringValuePtr(obj))) {
+ ossl_raise(eOSSLError, NULL);
+ }
+ }
+ if (!(ai = BN_to_ASN1_INTEGER(bn, ai))) {
+ BN_free(bn);
+ ossl_raise(eOSSLError, NULL);
+ }
+ BN_free(bn);
+ return ai;
+}
+#else
+ASN1_INTEGER *
+num_to_asn1integer(VALUE obj, ASN1_INTEGER *ai)
+{
+ BIGNUM *bn = GetBNPtr(obj);
+
+ if (!(ai = BN_to_ASN1_INTEGER(bn, ai))) {
+ ossl_raise(eOSSLError, NULL);
+ }
+ return ai;
+}
+#endif
+
+/********/
+/*
+ * ASN1 module
+ */
+#define ossl_asn1_get_value(o) rb_attr_get((o),rb_intern("@value"))
+#define ossl_asn1_get_tag(o) rb_attr_get((o),rb_intern("@tag"))
+#define ossl_asn1_get_tagging(o) rb_attr_get((o),rb_intern("@tagging"))
+#define ossl_asn1_get_tag_class(o) rb_attr_get((o),rb_intern("@tag_class"))
+
+#define ossl_asn1_set_value(o,v) rb_iv_set((o),"@value",(v))
+#define ossl_asn1_set_tag(o,v) rb_iv_set((o),"@tag",(v))
+#define ossl_asn1_set_tagging(o,v) rb_iv_set((o),"@tagging",(v))
+#define ossl_asn1_set_tag_class(o,v) rb_iv_set((o),"@tag_class",(v))
+
+VALUE mASN1;
+VALUE eASN1Error;
+
+VALUE cASN1Data;
+VALUE cASN1Primitive;
+VALUE cASN1Constructive;
+
+VALUE cASN1Boolean; /* BOOLEAN */
+VALUE cASN1Integer, cASN1Enumerated; /* INTEGER */
+VALUE cASN1BitString; /* BIT STRING */
+VALUE cASN1OctetString, cASN1UTF8String; /* STRINGs */
+VALUE cASN1NumericString, cASN1PrintableString;
+VALUE cASN1T61String, cASN1VideotexString;
+VALUE cASN1IA5String, cASN1GraphicString;
+VALUE cASN1ISO64String, cASN1GeneralString;
+VALUE cASN1UniversalString, cASN1BMPString;
+VALUE cASN1Null; /* NULL */
+VALUE cASN1ObjectId; /* OBJECT IDENTIFIER */
+VALUE cASN1UTCTime, cASN1GeneralizedTime; /* TIME */
+VALUE cASN1Sequence, cASN1Set; /* CONSTRUCTIVE */
+
+static ID sIMPLICIT, sEXPLICIT;
+static ID sUNIVERSAL, sAPPLICATION, sCONTEXT_SPECIFIC, sPRIVATE;
+
+/*
+ * Ruby to ASN1 converters
+ */
+static ASN1_BOOLEAN
+obj_to_asn1bool(VALUE obj)
+{
+ return RTEST(obj) ? 0xff : 0x100;
+}
+
+static ASN1_INTEGER*
+obj_to_asn1int(VALUE obj)
+{
+ return num_to_asn1integer(obj, NULL);
+}
+
+static ASN1_BIT_STRING*
+obj_to_asn1bstr(VALUE obj, long unused_bits)
+{
+ ASN1_BIT_STRING *bstr;
+
+ if(unused_bits < 0) unused_bits = 0;
+ StringValue(obj);
+ if(!(bstr = ASN1_BIT_STRING_new()))
+ ossl_raise(eASN1Error, NULL);
+ ASN1_BIT_STRING_set(bstr, RSTRING(obj)->ptr, RSTRING(obj)->len);
+ bstr->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07); /* clear */
+ bstr->flags |= ASN1_STRING_FLAG_BITS_LEFT|(unused_bits&0x07);
+
+ return bstr;
+}
+
+static ASN1_STRING*
+obj_to_asn1str(VALUE obj)
+{
+ ASN1_STRING *str;
+
+ StringValue(obj);
+ if(!(str = ASN1_STRING_new()))
+ ossl_raise(eASN1Error, NULL);
+ ASN1_STRING_set(str, RSTRING(obj)->ptr, RSTRING(obj)->len);
+
+ return str;
+}
+
+static ASN1_NULL*
+obj_to_asn1null(VALUE obj)
+{
+ ASN1_NULL *null;
+
+ if(!NIL_P(obj))
+ ossl_raise(eASN1Error, "nil expected");
+ if(!(null = ASN1_NULL_new()))
+ ossl_raise(eASN1Error, NULL);
+
+ return null;
+}
+
+static ASN1_OBJECT*
+obj_to_asn1obj(VALUE obj)
+{
+ ASN1_OBJECT *a1obj;
+
+ StringValue(obj);
+ a1obj = OBJ_txt2obj(RSTRING(obj)->ptr, 0);
+ if(!a1obj) a1obj = OBJ_txt2obj(RSTRING(obj)->ptr, 1);
+ if(!a1obj) ossl_raise(eASN1Error, "invalid OBJECT ID");
+
+ return a1obj;
+}
+
+static ASN1_UTCTIME*
+obj_to_asn1utime(VALUE time)
+{
+ time_t sec;
+ ASN1_UTCTIME *t;
+
+ sec = time_to_time_t(time);
+ if(!(t = ASN1_UTCTIME_set(NULL, sec)))
+ ossl_raise(eASN1Error, NULL);
+
+ return t;
+}
+
+static ASN1_GENERALIZEDTIME*
+obj_to_asn1gtime(VALUE time)
+{
+ time_t sec;
+ ASN1_GENERALIZEDTIME *t;
+
+ sec = time_to_time_t(time);
+ if(!(t =ASN1_GENERALIZEDTIME_set(NULL, sec)))
+ ossl_raise(eASN1Error, NULL);
+
+ return t;
+}
+
+static ASN1_STRING*
+obj_to_asn1derstr(VALUE obj)
+{
+ ASN1_STRING *a1str;
+ VALUE str;
+
+ str = ossl_to_der(obj);
+ if(!(a1str = ASN1_STRING_new()))
+ ossl_raise(eASN1Error, NULL);
+ ASN1_STRING_set(a1str, RSTRING(str)->ptr, RSTRING(str)->len);
+
+ return a1str;
+}
+
+/*
+ * DER to Ruby converters
+ */
+static VALUE
+decode_bool(unsigned char* der, int length)
+{
+ int bool;
+ unsigned char *p;
+
+ p = der;
+ if((bool = d2i_ASN1_BOOLEAN(NULL, &p, length)) < 0)
+ ossl_raise(eASN1Error, NULL);
+
+ return bool ? Qtrue : Qfalse;
+}
+
+static VALUE
+decode_int(unsigned char* der, int length)
+{
+ ASN1_INTEGER *ai;
+ unsigned char *p;
+ VALUE ret;
+ int status = 0;
+
+ p = der;
+ if(!(ai = d2i_ASN1_INTEGER(NULL, &p, length)))
+ ossl_raise(eASN1Error, NULL);
+ ret = rb_protect((VALUE(*)_((VALUE)))asn1integer_to_num,
+ (VALUE)ai, &status);
+ ASN1_INTEGER_free(ai);
+ if(status) rb_jump_tag(status);
+
+ return ret;
+}
+
+static VALUE
+decode_bstr(unsigned char* der, int length, long *unused_bits)
+{
+ ASN1_BIT_STRING *bstr;
+ unsigned char *p, *buf;
+ long len;
+ VALUE ret;
+
+ p = der;
+ if(!(bstr = d2i_ASN1_BIT_STRING(NULL, &p, length)))
+ ossl_raise(eASN1Error, NULL);
+ len = bstr->length;
+ if(!(buf = OPENSSL_malloc(len))){
+ ASN1_BIT_STRING_free(bstr);
+ ossl_raise(eASN1Error, NULL);
+ }
+ *unused_bits = 0;
+ if(bstr->flags & ASN1_STRING_FLAG_BITS_LEFT)
+ *unused_bits = bstr->flags & 0x07;
+ memcpy(buf, bstr->data, len);
+ ASN1_BIT_STRING_free(bstr);
+ ret = ossl_buf2str(buf, len);
+
+ return ret;
+}
+
+static VALUE
+decode_enum(unsigned char* der, int length)
+{
+ ASN1_ENUMERATED *ai;
+ unsigned char *p;
+ VALUE ret;
+ int status = 0;
+
+ p = der;
+ if(!(ai = d2i_ASN1_ENUMERATED(NULL, &p, length)))
+ ossl_raise(eASN1Error, NULL);
+ ret = rb_protect((VALUE(*)_((VALUE)))asn1integer_to_num,
+ (VALUE)ai, &status);
+ ASN1_ENUMERATED_free(ai);
+ if(status) rb_jump_tag(status);
+
+ return ret;
+}
+
+static VALUE
+decode_null(unsigned char* der, int length)
+{
+ ASN1_NULL *null;
+ unsigned char *p;
+
+ p = der;
+ if(!(null = d2i_ASN1_NULL(NULL, &p, length)))
+ ossl_raise(eASN1Error, NULL);
+ ASN1_NULL_free(null);
+
+ return Qnil;
+}
+
+static VALUE
+decode_obj(unsigned char* der, int length)
+{
+ ASN1_OBJECT *obj;
+ unsigned char *p;
+ VALUE ret;
+ int nid;
+ BIO *bio;
+
+ p = der;
+ if(!(obj = d2i_ASN1_OBJECT(NULL, &p, length)))
+ ossl_raise(eASN1Error, NULL);
+ if((nid = OBJ_obj2nid(obj)) != NID_undef){
+ ASN1_OBJECT_free(obj);
+ ret = rb_str_new2(OBJ_nid2sn(nid));
+ }
+ else{
+ if(!(bio = BIO_new(BIO_s_mem()))){
+ ASN1_OBJECT_free(obj);
+ ossl_raise(eASN1Error, NULL);
+ }
+ i2a_ASN1_OBJECT(bio, obj);
+ ASN1_OBJECT_free(obj);
+ ret = ossl_membio2str(bio);
+ }
+
+ return ret;
+}
+
+static VALUE
+decode_time(unsigned char* der, int length)
+{
+ ASN1_TIME *time;
+ unsigned char *p;
+ VALUE ret;
+ int status = 0;
+
+ p = der;
+ if(!(time = d2i_ASN1_TIME(NULL, &p, length)))
+ ossl_raise(eASN1Error, NULL);
+ ret = rb_protect((VALUE(*)_((VALUE)))asn1time_to_time,
+ (VALUE)time, &status);
+ ASN1_TIME_free(time);
+ if(status) rb_jump_tag(status);
+
+ return ret;
+}
+
+/********/
+
+typedef struct {
+ char *name;
+ VALUE *klass;
+} ossl_asn1_info_t;
+
+static ossl_asn1_info_t ossl_asn1_info[] = {
+ { "EOC", NULL, }, /* 0 */
+ { "BOOLEAN", &cASN1Boolean, }, /* 1 */
+ { "INTEGER", &cASN1Integer, }, /* 2 */
+ { "BIT_STRING", &cASN1BitString, }, /* 3 */
+ { "OCTET_STRING", &cASN1OctetString, }, /* 4 */
+ { "NULL", &cASN1Null, }, /* 5 */
+ { "OBJECT", &cASN1ObjectId, }, /* 6 */
+ { "OBJECT_DESCRIPTOR", NULL, }, /* 7 */
+ { "EXTERNAL", NULL, }, /* 8 */
+ { "REAL", NULL, }, /* 9 */
+ { "ENUMERATED", &cASN1Enumerated, }, /* 10 */
+ { "EMBEDDED_PDV", NULL, }, /* 11 */
+ { "UTF8STRING", &cASN1UTF8String, }, /* 12 */
+ { "RELATIVE_OID", NULL, }, /* 13 */
+ { "[UNIVERSAL 14]", NULL, }, /* 14 */
+ { "[UNIVERSAL 15]", NULL, }, /* 15 */
+ { "SEQUENCE", &cASN1Sequence, }, /* 16 */
+ { "SET", &cASN1Set, }, /* 17 */
+ { "NUMERICSTRING", &cASN1NumericString, }, /* 18 */
+ { "PRINTABLESTRING", &cASN1PrintableString, }, /* 19 */
+ { "T61STRING", &cASN1T61String, }, /* 20 */
+ { "VIDEOTEXSTRING", &cASN1VideotexString, }, /* 21 */
+ { "IA5STRING", &cASN1IA5String, }, /* 22 */
+ { "UTCTIME", &cASN1UTCTime, }, /* 23 */
+ { "GENERALIZEDTIME", &cASN1GeneralizedTime, }, /* 24 */
+ { "GRAPHICSTRING", &cASN1GraphicString, }, /* 25 */
+ { "ISO64STRING", &cASN1ISO64String, }, /* 26 */
+ { "GENERALSTRING", &cASN1GeneralString, }, /* 27 */
+ { "UNIVERSALSTRING", &cASN1UniversalString, }, /* 28 */
+ { "CHARACTER_STRING", NULL, }, /* 29 */
+ { "BMPSTRING", &cASN1BMPString, }, /* 30 */
+};
+
+int ossl_asn1_info_size = (sizeof(ossl_asn1_info)/sizeof(ossl_asn1_info[0]));
+
+static int ossl_asn1_default_tag(VALUE obj);
+
+ASN1_TYPE*
+ossl_asn1_get_asn1type(VALUE obj)
+{
+ ASN1_TYPE *ret;
+ VALUE value, rflag;
+ void *ptr;
+ void (*free_func)();
+ long tag, flag;
+
+ tag = ossl_asn1_default_tag(obj);
+ value = ossl_asn1_get_value(obj);
+ switch(tag){
+ case V_ASN1_BOOLEAN:
+ ptr = (void*)obj_to_asn1bool(value);
+ free_func = NULL;
+ break;
+ case V_ASN1_INTEGER: /* FALLTHROUGH */
+ case V_ASN1_ENUMERATED:
+ ptr = obj_to_asn1int(value);
+ free_func = ASN1_INTEGER_free;
+ break;
+ case V_ASN1_BIT_STRING:
+ rflag = rb_attr_get(obj, rb_intern("@unused_bits"));
+ flag = NIL_P(rflag) ? -1 : NUM2INT(rflag);
+ ptr = obj_to_asn1bstr(value, flag);
+ free_func = ASN1_BIT_STRING_free;
+ break;
+ case V_ASN1_NULL:
+ ptr = obj_to_asn1null(value);
+ free_func = ASN1_NULL_free;
+ break;
+ case V_ASN1_OCTET_STRING: /* FALLTHROUGH */
+ case V_ASN1_UTF8STRING: /* FALLTHROUGH */
+ case V_ASN1_NUMERICSTRING: /* FALLTHROUGH */
+ case V_ASN1_PRINTABLESTRING: /* FALLTHROUGH */
+ case V_ASN1_T61STRING: /* FALLTHROUGH */
+ case V_ASN1_VIDEOTEXSTRING: /* FALLTHROUGH */
+ case V_ASN1_IA5STRING: /* FALLTHROUGH */
+ case V_ASN1_GRAPHICSTRING: /* FALLTHROUGH */
+ case V_ASN1_ISO64STRING: /* FALLTHROUGH */
+ case V_ASN1_GENERALSTRING: /* FALLTHROUGH */
+ case V_ASN1_UNIVERSALSTRING: /* FALLTHROUGH */
+ case V_ASN1_BMPSTRING:
+ ptr = obj_to_asn1str(value);
+ free_func = ASN1_STRING_free;
+ break;
+ case V_ASN1_OBJECT:
+ ptr = obj_to_asn1obj(value);
+ free_func = ASN1_OBJECT_free;
+ break;
+ case V_ASN1_UTCTIME:
+ ptr = obj_to_asn1utime(value);
+ free_func = ASN1_TIME_free;
+ break;
+ case V_ASN1_GENERALIZEDTIME:
+ ptr = obj_to_asn1gtime(value);
+ free_func = ASN1_TIME_free;
+ break;
+ case V_ASN1_SET: /* FALLTHROUGH */
+ case V_ASN1_SEQUENCE:
+ ptr = obj_to_asn1derstr(obj);
+ free_func = ASN1_STRING_free;
+ break;
+ default:
+ ossl_raise(eASN1Error, "unsupported ASN.1 type");
+ }
+ if(!(ret = OPENSSL_malloc(sizeof(ASN1_TYPE)))){
+ if(free_func) free_func(ptr);
+ ossl_raise(eASN1Error, "ASN1_TYPE alloc failure");
+ }
+ memset(ret, 0, sizeof(ASN1_TYPE));
+ ASN1_TYPE_set(ret, tag, ptr);
+
+ return ret;
+}
+
+static int
+ossl_asn1_default_tag(VALUE obj)
+{
+ int i;
+
+ for(i = 0; i < ossl_asn1_info_size; i++){
+ if(ossl_asn1_info[i].klass &&
+ rb_obj_is_kind_of(obj, *ossl_asn1_info[i].klass)){
+ return i;
+ }
+ }
+ ossl_raise(eASN1Error, "universal tag for %s not found",
+ rb_class2name(CLASS_OF(obj)));
+
+ return -1; /* dummy */
+}
+
+static int
+ossl_asn1_tag(VALUE obj)
+{
+ VALUE tag;
+
+ tag = ossl_asn1_get_tag(obj);
+ if(NIL_P(tag))
+ ossl_raise(eASN1Error, "tag number not specified");
+
+ return NUM2INT(tag);
+}
+
+static int
+ossl_asn1_is_explicit(VALUE obj)
+{
+ VALUE s;
+ int ret = -1;
+
+ s = ossl_asn1_get_tagging(obj);
+ if(NIL_P(s)) return 0;
+ else if(SYMBOL_P(s)){
+ if (SYM2ID(s) == sIMPLICIT)
+ ret = 0;
+ else if (SYM2ID(s) == sEXPLICIT)
+ ret = 1;
+ }
+ if(ret < 0){
+ ossl_raise(eASN1Error, "invalid tag default");
+ }
+
+ return ret;
+}
+
+static int
+ossl_asn1_tag_class(VALUE obj)
+{
+ VALUE s;
+ int ret = -1;
+
+ s = ossl_asn1_get_tag_class(obj);
+ if(NIL_P(s)) ret = V_ASN1_UNIVERSAL;
+ else if(SYMBOL_P(s)){
+ if (SYM2ID(s) == sUNIVERSAL)
+ ret = V_ASN1_UNIVERSAL;
+ else if (SYM2ID(s) == sAPPLICATION)
+ ret = V_ASN1_APPLICATION;
+ else if (SYM2ID(s) == sCONTEXT_SPECIFIC)
+ ret = V_ASN1_CONTEXT_SPECIFIC;
+ else if (SYM2ID(s) == sPRIVATE)
+ ret = V_ASN1_PRIVATE;
+ }
+ if(ret < 0){
+ ossl_raise(eASN1Error, "invalid tag class");
+ }
+
+ return ret;
+}
+
+static VALUE
+ossl_asn1_class2sym(int tc)
+{
+ if((tc & V_ASN1_PRIVATE) == V_ASN1_PRIVATE)
+ return ID2SYM(sPRIVATE);
+ else if((tc & V_ASN1_CONTEXT_SPECIFIC) == V_ASN1_CONTEXT_SPECIFIC)
+ return ID2SYM(sCONTEXT_SPECIFIC);
+ else if((tc & V_ASN1_APPLICATION) == V_ASN1_APPLICATION)
+ return ID2SYM(sAPPLICATION);
+ else
+ return ID2SYM(sUNIVERSAL);
+}
+
+static VALUE
+ossl_asn1data_initialize(VALUE self, VALUE value, VALUE tag, VALUE tag_class)
+{
+ if(!SYMBOL_P(tag_class))
+ ossl_raise(eASN1Error, "invalid tag class");
+ if((SYM2ID(tag_class) == sUNIVERSAL) && NUM2INT(tag) > 31)
+ ossl_raise(eASN1Error, "tag number for Universal too large");
+ ossl_asn1_set_tag(self, tag);
+ ossl_asn1_set_value(self, value);
+ ossl_asn1_set_tag_class(self, tag_class);
+
+ return self;
+}
+
+static VALUE
+join_der_i(VALUE i, VALUE str)
+{
+ i = ossl_to_der_if_possible(i);
+ StringValue(i);
+ rb_str_append(str, i);
+ return Qnil;
+}
+
+static VALUE
+join_der(VALUE enumerable)
+{
+ VALUE str = rb_str_new(0, 0);
+ rb_iterate(rb_each, enumerable, join_der_i, str);
+ return str;
+}
+
+static VALUE
+ossl_asn1data_to_der(VALUE self)
+{
+ VALUE value, der;
+ int tag, tag_class, is_cons = 0;
+ long length;
+ unsigned char *p;
+
+ value = ossl_asn1_get_value(self);
+ if(rb_obj_is_kind_of(value, rb_cArray)){
+ is_cons = 1;
+ value = join_der(value);
+ }
+ StringValue(value);
+
+ tag = ossl_asn1_tag(self);
+ tag_class = ossl_asn1_tag_class(self);
+ if((length = ASN1_object_size(1, RSTRING(value)->len, tag)) <= 0)
+ ossl_raise(eASN1Error, NULL);
+ der = rb_str_new(0, length);
+ p = RSTRING(der)->ptr;
+ ASN1_put_object(&p, is_cons, RSTRING(value)->len, tag, tag_class);
+ memcpy(p, RSTRING(value)->ptr, RSTRING(value)->len);
+ p += RSTRING(value)->len;
+ ossl_str_adjust(der, p);
+
+ return der;
+}
+
+static VALUE
+ossl_asn1_decode0(unsigned char **pp, long length, long *offset, long depth,
+ int once, int yield)
+{
+ unsigned char *start, *p;
+ long len, off = *offset;
+ int hlen, tag, tc, j;
+ VALUE ary, asn1data, value, tag_class;
+
+ ary = rb_ary_new();
+ p = *pp;
+ while(length > 0){
+ start = p;
+ j = ASN1_get_object(&p, &len, &tag, &tc, length);
+ if(j & 0x80) ossl_raise(eASN1Error, NULL);
+ hlen = p - start;
+ if(yield){
+ VALUE arg = rb_ary_new();
+ rb_ary_push(arg, LONG2NUM(depth));
+ rb_ary_push(arg, LONG2NUM(off));
+ rb_ary_push(arg, LONG2NUM(hlen));
+ rb_ary_push(arg, LONG2NUM(len));
+ rb_ary_push(arg, (j & V_ASN1_CONSTRUCTED) ? Qtrue : Qfalse);
+ rb_ary_push(arg, ossl_asn1_class2sym(tc));
+ rb_ary_push(arg, INT2NUM(tag));
+ rb_yield(arg);
+ }
+ length -= hlen;
+ off += hlen;
+ if(len > length) ossl_raise(eASN1Error, "value is too short");
+ if((tc & V_ASN1_PRIVATE) == V_ASN1_PRIVATE)
+ tag_class = sPRIVATE;
+ else if((tc & V_ASN1_CONTEXT_SPECIFIC) == V_ASN1_CONTEXT_SPECIFIC)
+ tag_class = sCONTEXT_SPECIFIC;
+ else if((tc & V_ASN1_APPLICATION) == V_ASN1_APPLICATION)
+ tag_class = sAPPLICATION;
+ else
+ tag_class = sUNIVERSAL;
+ if(j & V_ASN1_CONSTRUCTED){
+ /* TODO: if j == 0x21 it is indefinite length object. */
+ if((j == 0x21) && (len == 0)){
+ long lastoff = off;
+ value = ossl_asn1_decode0(&p, length, &off, depth+1, 0, yield);
+ len = off - lastoff;
+ }
+ else value = ossl_asn1_decode0(&p, len, &off, depth+1, 0, yield);
+ }
+ else{
+ value = rb_str_new(p, len);
+ p += len;
+ off += len;
+ }
+ if(tag_class == sUNIVERSAL &&
+ tag < ossl_asn1_info_size && ossl_asn1_info[tag].klass){
+ VALUE klass = *ossl_asn1_info[tag].klass;
+ long flag = 0;
+ if(!rb_obj_is_kind_of(value, rb_cArray)){
+ switch(tag){
+ case V_ASN1_BOOLEAN:
+ value = decode_bool(start, hlen+len);
+ break;
+ case V_ASN1_INTEGER:
+ value = decode_int(start, hlen+len);
+ break;
+ case V_ASN1_BIT_STRING:
+ value = decode_bstr(start, hlen+len, &flag);
+ break;
+ case V_ASN1_NULL:
+ value = decode_null(start, hlen+len);
+ break;
+ case V_ASN1_ENUMERATED:
+ value = decode_enum(start, hlen+len);
+ break;
+ case V_ASN1_OBJECT:
+ value = decode_obj(start, hlen+len);
+ break;
+ case V_ASN1_UTCTIME: /* FALLTHROUGH */
+ case V_ASN1_GENERALIZEDTIME:
+ value = decode_time(start, hlen+len);
+ break;
+ default:
+ /* use original value */
+ break;
+ }
+ }
+ asn1data = rb_funcall(klass, rb_intern("new"), 1, value);
+ if(tag == V_ASN1_BIT_STRING){
+ rb_iv_set(asn1data, "@unused_bits", LONG2NUM(flag));
+ }
+ }
+ else{
+ asn1data = rb_funcall(cASN1Data, rb_intern("new"), 3,
+ value, INT2NUM(tag), ID2SYM(tag_class));
+ }
+ rb_ary_push(ary, asn1data);
+ length -= len;
+ if(once) break;
+ }
+ *pp = p;
+ *offset = off;
+
+ return ary;
+}
+
+static VALUE
+ossl_asn1_traverse(VALUE self, VALUE obj)
+{
+ unsigned char *p;
+ long offset = 0;
+ volatile VALUE tmp;
+
+ obj = ossl_to_der_if_possible(obj);
+ tmp = rb_str_new4(StringValue(obj));
+ p = RSTRING(tmp)->ptr;
+ ossl_asn1_decode0(&p, RSTRING(tmp)->len, &offset, 0, 0, 1);
+
+ return Qnil;
+}
+
+static VALUE
+ossl_asn1_decode(VALUE self, VALUE obj)
+{
+ VALUE ret, ary;
+ unsigned char *p;
+ long offset = 0;
+ volatile VALUE tmp;
+
+ obj = ossl_to_der_if_possible(obj);
+ tmp = rb_str_new4(StringValue(obj));
+ p = RSTRING(tmp)->ptr;
+ ary = ossl_asn1_decode0(&p, RSTRING(tmp)->len, &offset, 0, 1, 0);
+ ret = rb_ary_entry(ary, 0);
+
+ return ret;
+}
+
+static VALUE
+ossl_asn1_decode_all(VALUE self, VALUE obj)
+{
+ VALUE ret;
+ unsigned char *p;
+ long offset = 0;
+ volatile VALUE tmp;
+
+ obj = ossl_to_der_if_possible(obj);
+ tmp = rb_str_new4(StringValue(obj));
+ p = RSTRING(tmp)->ptr;
+ ret = ossl_asn1_decode0(&p, RSTRING(tmp)->len, &offset, 0, 0, 0);
+
+ return ret;
+}
+
+static VALUE
+ossl_asn1_initialize(int argc, VALUE *argv, VALUE self)
+{
+ VALUE value, tag, tagging, tag_class;
+
+ rb_scan_args(argc, argv, "13", &value, &tag, &tagging, &tag_class);
+ if(argc > 1){
+ if(NIL_P(tag))
+ ossl_raise(eASN1Error, "must specify tag number");
+ if(NIL_P(tagging))
+ tagging = ID2SYM(sEXPLICIT);
+ if(!SYMBOL_P(tagging))
+ ossl_raise(eASN1Error, "invalid tag default");
+ if(NIL_P(tag_class))
+ tag_class = ID2SYM(sCONTEXT_SPECIFIC);
+ if(!SYMBOL_P(tag_class))
+ ossl_raise(eASN1Error, "invalid tag class");
+ if(SYM2ID(tagging) == sIMPLICIT && NUM2INT(tag) > 31)
+ ossl_raise(eASN1Error, "tag number for Universal too large");
+ }
+ else{
+ tag = INT2NUM(ossl_asn1_default_tag(self));
+ tagging = Qnil;
+ tag_class = ID2SYM(sUNIVERSAL);
+ }
+ ossl_asn1_set_tag(self, tag);
+ ossl_asn1_set_value(self, value);
+ ossl_asn1_set_tagging(self, tagging);
+ ossl_asn1_set_tag_class(self, tag_class);
+
+ return self;
+}
+
+static int
+ossl_i2d_ASN1_TYPE(ASN1_TYPE *a, unsigned char **pp)
+{
+#if OPENSSL_VERSION_NUMBER < 0x00907000L
+ if(!a) return 0;
+ if(a->type == V_ASN1_BOOLEAN)
+ return i2d_ASN1_BOOLEAN(a->value.boolean, pp);
+#endif
+ return i2d_ASN1_TYPE(a, pp);
+}
+
+static void
+ossl_ASN1_TYPE_free(ASN1_TYPE *a)
+{
+#if OPENSSL_VERSION_NUMBER < 0x00907000L
+ if(!a) return;
+ if(a->type == V_ASN1_BOOLEAN){
+ OPENSSL_free(a);
+ return;
+ }
+#endif
+ ASN1_TYPE_free(a);
+}
+
+static VALUE
+ossl_asn1prim_to_der(VALUE self)
+{
+ ASN1_TYPE *asn1;
+ int tn, tc, explicit;
+ long length, reallen;
+ unsigned char *buf, *p;
+ VALUE str;
+
+ tn = NUM2INT(ossl_asn1_get_tag(self));
+ tc = ossl_asn1_tag_class(self);
+ explicit = ossl_asn1_is_explicit(self);
+ asn1 = ossl_asn1_get_asn1type(self);
+
+ length = ASN1_object_size(1, ossl_i2d_ASN1_TYPE(asn1, NULL), tn);
+ if(!(buf = OPENSSL_malloc(length))){
+ ossl_ASN1_TYPE_free(asn1);
+ ossl_raise(eASN1Error, "cannot alloc buffer");
+ }
+ p = buf;
+ if(tc == V_ASN1_UNIVERSAL) ossl_i2d_ASN1_TYPE(asn1, &p);
+ else{
+ if(explicit){
+ ASN1_put_object(&p, 1, ossl_i2d_ASN1_TYPE(asn1, NULL), tn, tc);
+ ossl_i2d_ASN1_TYPE(asn1, &p);
+ }
+ else{
+ ossl_i2d_ASN1_TYPE(asn1, &p);
+ *buf = tc | tn | (*buf & V_ASN1_CONSTRUCTED);
+ }
+ }
+ ossl_ASN1_TYPE_free(asn1);
+ reallen = p - buf;
+ assert(reallen <= length);
+ str = ossl_buf2str(buf, reallen); /* buf will be free in ossl_buf2str */
+
+ return str;
+}
+
+static VALUE
+ossl_asn1cons_to_der(VALUE self)
+{
+ int tag, tn, tc, explicit;
+ long seq_len, length;
+ unsigned char *p;
+ VALUE value, str;
+
+ tag = ossl_asn1_default_tag(self);
+ tn = NUM2INT(ossl_asn1_get_tag(self));
+ tc = ossl_asn1_tag_class(self);
+ explicit = ossl_asn1_is_explicit(self);
+ value = join_der(ossl_asn1_get_value(self));
+
+ seq_len = ASN1_object_size(1, RSTRING(value)->len, tag);
+ length = ASN1_object_size(1, seq_len, tn);
+ str = rb_str_new(0, length);
+ p = RSTRING(str)->ptr;
+ if(tc == V_ASN1_UNIVERSAL)
+ ASN1_put_object(&p, 1, RSTRING(value)->len, tn, tc);
+ else{
+ if(explicit){
+ ASN1_put_object(&p, 1, seq_len, tn, tc);
+ ASN1_put_object(&p, 1, RSTRING(value)->len, tag, V_ASN1_UNIVERSAL);
+ }
+ else ASN1_put_object(&p, 1, RSTRING(value)->len, tn, tc);
+ }
+ memcpy(p, RSTRING(value)->ptr, RSTRING(value)->len);
+ p += RSTRING(value)->len;
+ ossl_str_adjust(str, p);
+
+ return str;
+}
+
+static VALUE
+ossl_asn1cons_each(VALUE self)
+{
+ rb_ary_each(ossl_asn1_get_value(self));
+ return self;
+}
+
+static VALUE
+ossl_asn1obj_s_register(VALUE self, VALUE oid, VALUE sn, VALUE ln)
+{
+ StringValue(oid);
+ StringValue(sn);
+ StringValue(ln);
+
+ if(!OBJ_create(RSTRING(oid)->ptr, RSTRING(sn)->ptr, RSTRING(ln)->ptr))
+ ossl_raise(eASN1Error, NULL);
+
+ return Qtrue;
+}
+
+static VALUE
+ossl_asn1obj_get_sn(VALUE self)
+{
+ VALUE val, ret = Qnil;
+ int nid;
+
+ val = ossl_asn1_get_value(self);
+ if ((nid = OBJ_txt2nid(StringValuePtr(val))) != NID_undef)
+ ret = rb_str_new2(OBJ_nid2sn(nid));
+
+ return ret;
+}
+
+static VALUE
+ossl_asn1obj_get_ln(VALUE self)
+{
+ VALUE val, ret = Qnil;
+ int nid;
+
+ val = ossl_asn1_get_value(self);
+ if ((nid = OBJ_txt2nid(StringValuePtr(val))) != NID_undef)
+ ret = rb_str_new2(OBJ_nid2ln(nid));
+
+ return ret;
+}
+
+static VALUE
+ossl_asn1obj_get_oid(VALUE self)
+{
+ VALUE val;
+ ASN1_OBJECT *a1obj;
+ char buf[128];
+
+ val = ossl_asn1_get_value(self);
+ a1obj = obj_to_asn1obj(val);
+ OBJ_obj2txt(buf, sizeof(buf), a1obj, 1);
+ ASN1_OBJECT_free(a1obj);
+
+ return rb_str_new2(buf);
+}
+
+#define OSSL_ASN1_IMPL_FACTORY_METHOD(klass) \
+static VALUE ossl_asn1_##klass(int argc, VALUE *argv, VALUE self)\
+{ return rb_funcall3(cASN1##klass, rb_intern("new"), argc, argv); }
+
+OSSL_ASN1_IMPL_FACTORY_METHOD(Boolean)
+OSSL_ASN1_IMPL_FACTORY_METHOD(Integer)
+OSSL_ASN1_IMPL_FACTORY_METHOD(Enumerated)
+OSSL_ASN1_IMPL_FACTORY_METHOD(BitString)
+OSSL_ASN1_IMPL_FACTORY_METHOD(OctetString)
+OSSL_ASN1_IMPL_FACTORY_METHOD(UTF8String)
+OSSL_ASN1_IMPL_FACTORY_METHOD(NumericString)
+OSSL_ASN1_IMPL_FACTORY_METHOD(PrintableString)
+OSSL_ASN1_IMPL_FACTORY_METHOD(T61String)
+OSSL_ASN1_IMPL_FACTORY_METHOD(VideotexString)
+OSSL_ASN1_IMPL_FACTORY_METHOD(IA5String)
+OSSL_ASN1_IMPL_FACTORY_METHOD(GraphicString)
+OSSL_ASN1_IMPL_FACTORY_METHOD(ISO64String)
+OSSL_ASN1_IMPL_FACTORY_METHOD(GeneralString)
+OSSL_ASN1_IMPL_FACTORY_METHOD(UniversalString)
+OSSL_ASN1_IMPL_FACTORY_METHOD(BMPString)
+OSSL_ASN1_IMPL_FACTORY_METHOD(Null)
+OSSL_ASN1_IMPL_FACTORY_METHOD(ObjectId)
+OSSL_ASN1_IMPL_FACTORY_METHOD(UTCTime)
+OSSL_ASN1_IMPL_FACTORY_METHOD(GeneralizedTime)
+OSSL_ASN1_IMPL_FACTORY_METHOD(Sequence)
+OSSL_ASN1_IMPL_FACTORY_METHOD(Set)
+
+void
+Init_ossl_asn1()
+{
+ VALUE ary;
+ int i;
+
+ sUNIVERSAL = rb_intern("UNIVERSAL");
+ sCONTEXT_SPECIFIC = rb_intern("CONTEXT_SPECIFIC");
+ sAPPLICATION = rb_intern("APPLICATION");
+ sPRIVATE = rb_intern("PRIVATE");
+ sEXPLICIT = rb_intern("EXPLICIT");
+ sIMPLICIT = rb_intern("IMPLICIT");
+
+ mASN1 = rb_define_module_under(mOSSL, "ASN1");
+ eASN1Error = rb_define_class_under(mASN1, "ASN1Error", eOSSLError);
+ rb_define_module_function(mASN1, "traverse", ossl_asn1_traverse, 1);
+ rb_define_module_function(mASN1, "decode", ossl_asn1_decode, 1);
+ rb_define_module_function(mASN1, "decode_all", ossl_asn1_decode_all, 1);
+ ary = rb_ary_new();
+ rb_define_const(mASN1, "UNIVERSAL_TAG_NAME", ary);
+ for(i = 0; i < ossl_asn1_info_size; i++){
+ if(ossl_asn1_info[i].name[0] == '[') continue;
+ rb_define_const(mASN1, ossl_asn1_info[i].name, INT2NUM(i));
+ rb_ary_store(ary, i, rb_str_new2(ossl_asn1_info[i].name));
+ }
+
+ cASN1Data = rb_define_class_under(mASN1, "ASN1Data", rb_cObject);
+ rb_attr(cASN1Data, rb_intern("value"), 1, 1, Qtrue);
+ rb_attr(cASN1Data, rb_intern("tag"), 1, 1, Qtrue);
+ rb_attr(cASN1Data, rb_intern("tag_class"), 1, 1, Qtrue);
+ rb_define_method(cASN1Data, "initialize", ossl_asn1data_initialize, 3);
+ rb_define_method(cASN1Data, "to_der", ossl_asn1data_to_der, 0);
+
+ cASN1Primitive = rb_define_class_under(mASN1, "Primitive", cASN1Data);
+ rb_attr(cASN1Primitive, rb_intern("tagging"), 1, 1, Qtrue);
+ rb_define_method(cASN1Primitive, "initialize", ossl_asn1_initialize, -1);
+ rb_define_method(cASN1Primitive, "to_der", ossl_asn1prim_to_der, 0);
+
+ cASN1Constructive = rb_define_class_under(mASN1,"Constructive", cASN1Data);
+ rb_include_module(cASN1Constructive, rb_mEnumerable);
+ rb_attr(cASN1Constructive, rb_intern("tagging"), 1, 1, Qtrue);
+ rb_define_method(cASN1Constructive, "initialize", ossl_asn1_initialize, -1);
+ rb_define_method(cASN1Constructive, "to_der", ossl_asn1cons_to_der, 0);
+ rb_define_method(cASN1Constructive, "each", ossl_asn1cons_each, 0);
+
+#define OSSL_ASN1_DEFINE_CLASS(name, super) \
+do{\
+ cASN1##name = rb_define_class_under(mASN1, #name, cASN1##super);\
+ rb_define_module_function(mASN1, #name, ossl_asn1_##name, -1);\
+}while(0)
+
+ OSSL_ASN1_DEFINE_CLASS(Boolean, Primitive);
+ OSSL_ASN1_DEFINE_CLASS(Integer, Primitive);
+ OSSL_ASN1_DEFINE_CLASS(Enumerated, Primitive);
+ OSSL_ASN1_DEFINE_CLASS(BitString, Primitive);
+ OSSL_ASN1_DEFINE_CLASS(OctetString, Primitive);
+ OSSL_ASN1_DEFINE_CLASS(UTF8String, Primitive);
+ OSSL_ASN1_DEFINE_CLASS(NumericString, Primitive);
+ OSSL_ASN1_DEFINE_CLASS(PrintableString, Primitive);
+ OSSL_ASN1_DEFINE_CLASS(T61String, Primitive);
+ OSSL_ASN1_DEFINE_CLASS(VideotexString, Primitive);
+ OSSL_ASN1_DEFINE_CLASS(IA5String, Primitive);
+ OSSL_ASN1_DEFINE_CLASS(GraphicString, Primitive);
+ OSSL_ASN1_DEFINE_CLASS(ISO64String, Primitive);
+ OSSL_ASN1_DEFINE_CLASS(GeneralString, Primitive);
+ OSSL_ASN1_DEFINE_CLASS(UniversalString, Primitive);
+ OSSL_ASN1_DEFINE_CLASS(BMPString, Primitive);
+ OSSL_ASN1_DEFINE_CLASS(Null, Primitive);
+ OSSL_ASN1_DEFINE_CLASS(ObjectId, Primitive);
+ OSSL_ASN1_DEFINE_CLASS(UTCTime, Primitive);
+ OSSL_ASN1_DEFINE_CLASS(GeneralizedTime, Primitive);
+
+ OSSL_ASN1_DEFINE_CLASS(Sequence, Constructive);
+ OSSL_ASN1_DEFINE_CLASS(Set, Constructive);
+
+ rb_define_singleton_method(cASN1ObjectId, "register", ossl_asn1obj_s_register, 3);
+ rb_define_method(cASN1ObjectId, "sn", ossl_asn1obj_get_sn, 0);
+ rb_define_method(cASN1ObjectId, "ln", ossl_asn1obj_get_ln, 0);
+ rb_define_method(cASN1ObjectId, "oid", ossl_asn1obj_get_oid, 0);
+ rb_define_alias(cASN1ObjectId, "short_name", "sn");
+ rb_define_alias(cASN1ObjectId, "long_name", "ln");
+ rb_attr(cASN1BitString, rb_intern("unused_bits"), 1, 1, Qtrue);
+}
diff --git a/ruby_1_8_5/ext/openssl/ossl_asn1.h b/ruby_1_8_5/ext/openssl/ossl_asn1.h
new file mode 100644
index 0000000000..6a1c97b902
--- /dev/null
+++ b/ruby_1_8_5/ext/openssl/ossl_asn1.h
@@ -0,0 +1,59 @@
+/*
+ * $Id: ossl_asn1.h,v 1.3.2.1 2005/09/10 01:17:00 gotoyuzo Exp $
+ * 'OpenSSL for Ruby' team members
+ * Copyright (C) 2003
+ * All rights reserved.
+ */
+/*
+ * This program is licenced under the same licence as Ruby.
+ * (See the file 'LICENCE'.)
+ */
+#if !defined(_OSSL_ASN1_H_)
+#define _OSSL_ASN1_H_
+
+/*
+ * ASN1_DATE conversions
+ */
+VALUE asn1time_to_time(ASN1_TIME *);
+time_t time_to_time_t(VALUE);
+
+/*
+ * ASN1_STRING conversions
+ */
+VALUE asn1str_to_str(ASN1_STRING *);
+
+/*
+ * ASN1_INTEGER conversions
+ */
+VALUE asn1integer_to_num(ASN1_INTEGER *);
+ASN1_INTEGER *num_to_asn1integer(VALUE, ASN1_INTEGER *);
+
+/*
+ * ASN1 module
+ */
+extern VALUE mASN1;
+extern VALUE eASN1Error;
+
+extern VALUE cASN1Data;
+extern VALUE cASN1Primitive;
+extern VALUE cASN1Constructive;
+
+extern VALUE cASN1Boolean; /* BOOLEAN */
+extern VALUE cASN1Integer, cASN1Enumerated; /* INTEGER */
+extern VALUE cASN1BitString; /* BIT STRING */
+extern VALUE cASN1OctetString, cASN1UTF8String; /* STRINGs */
+extern VALUE cASN1NumericString, cASN1PrintableString;
+extern VALUE cASN1T61String, cASN1VideotexString;
+extern VALUE cASN1IA5String, cASN1GraphicString;
+extern VALUE cASN1ISO64String, cASN1GeneralString;
+extern VALUE cASN1UniversalString, cASN1BMPString;
+extern VALUE cASN1Null; /* NULL */
+extern VALUE cASN1ObjectId; /* OBJECT IDENTIFIER */
+extern VALUE cASN1UTCTime, cASN1GeneralizedTime; /* TIME */
+extern VALUE cASN1Sequence, cASN1Set; /* CONSTRUCTIVE */
+
+ASN1_TYPE *ossl_asn1_get_asn1type(VALUE);
+
+void Init_ossl_asn1(void);
+
+#endif
diff --git a/ruby_1_8_5/ext/openssl/ossl_bio.c b/ruby_1_8_5/ext/openssl/ossl_bio.c
new file mode 100644
index 0000000000..4e3248eb1d
--- /dev/null
+++ b/ruby_1_8_5/ext/openssl/ossl_bio.c
@@ -0,0 +1,73 @@
+/*
+ * $Id: ossl_bio.c,v 1.2.2.1 2005/06/19 16:29:17 gotoyuzo Exp $
+ * 'OpenSSL for Ruby' team members
+ * Copyright (C) 2003
+ * All rights reserved.
+ */
+/*
+ * This program is licenced under the same licence as Ruby.
+ * (See the file 'LICENCE'.)
+ */
+#include "ossl.h"
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+BIO *
+ossl_obj2bio(VALUE obj)
+{
+ BIO *bio;
+
+ if (TYPE(obj) == T_FILE) {
+ OpenFile *fptr;
+ GetOpenFile(obj, fptr);
+ rb_io_check_readable(fptr);
+ bio = BIO_new_fp(fptr->f, BIO_NOCLOSE);
+ }
+ else {
+ StringValue(obj);
+ bio = BIO_new_mem_buf(RSTRING(obj)->ptr, RSTRING(obj)->len);
+ }
+ if (!bio) ossl_raise(eOSSLError, NULL);
+
+ return bio;
+}
+
+BIO *
+ossl_protect_obj2bio(VALUE obj, int *status)
+{
+ BIO *ret = NULL;
+ ret = (BIO*)rb_protect((VALUE(*)_((VALUE)))ossl_obj2bio, obj, status);
+ return ret;
+}
+
+VALUE
+ossl_membio2str0(BIO *bio)
+{
+ VALUE ret;
+ BUF_MEM *buf;
+
+ BIO_get_mem_ptr(bio, &buf);
+ ret = rb_str_new(buf->data, buf->length);
+
+ return ret;
+}
+
+VALUE
+ossl_protect_membio2str(BIO *bio, int *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/ruby_1_8_5/ext/openssl/ossl_bio.h b/ruby_1_8_5/ext/openssl/ossl_bio.h
new file mode 100644
index 0000000000..ca312679fa
--- /dev/null
+++ b/ruby_1_8_5/ext/openssl/ossl_bio.h
@@ -0,0 +1,21 @@
+/*
+ * $Id: ossl_bio.h,v 1.2 2003/09/17 09:05:01 gotoyuzo Exp $
+ * 'OpenSSL for Ruby' team members
+ * Copyright (C) 2003
+ * All rights reserved.
+ */
+/*
+ * This program is licenced under the same licence as Ruby.
+ * (See the file 'LICENCE'.)
+ */
+#if !defined(_OSSL_BIO_H_)
+#define _OSSL_BIO_H_
+
+BIO *ossl_obj2bio(VALUE);
+BIO *ossl_protect_obj2bio(VALUE,int*);
+VALUE ossl_membio2str0(BIO*);
+VALUE ossl_membio2str(BIO*);
+VALUE ossl_protect_membio2str(BIO*,int*);
+
+#endif
+
diff --git a/ruby_1_8_5/ext/openssl/ossl_bn.c b/ruby_1_8_5/ext/openssl/ossl_bn.c
new file mode 100644
index 0000000000..fb86c8721c
--- /dev/null
+++ b/ruby_1_8_5/ext/openssl/ossl_bn.c
@@ -0,0 +1,715 @@
+/*
+ * $Id: ossl_bn.c,v 1.5.2.1 2004/12/15 01:54:39 matz Exp $
+ * 'OpenSSL for Ruby' project
+ * Copyright (C) 2001-2002 Technorama team <oss-ruby@technorama.net>
+ * All rights reserved.
+ */
+/*
+ * This program is licenced under the same licence as Ruby.
+ * (See the file 'LICENCE'.)
+ */
+/* modified by Michal Rokos <m.rokos@sh.cvut.cz> */
+#include "ossl.h"
+
+#define WrapBN(klass, obj, bn) do { \
+ if (!bn) { \
+ ossl_raise(rb_eRuntimeError, "BN wasn't initialized!"); \
+ } \
+ obj = Data_Wrap_Struct(klass, 0, BN_clear_free, bn); \
+} while (0)
+
+#define GetBN(obj, bn) do { \
+ Data_Get_Struct(obj, BIGNUM, bn); \
+ if (!bn) { \
+ ossl_raise(rb_eRuntimeError, "BN wasn't initialized!"); \
+ } \
+} while (0)
+
+#define SafeGetBN(obj, bn) do { \
+ OSSL_Check_Kind(obj, cBN); \
+ GetBN(obj, bn); \
+} while (0)
+
+/*
+ * Classes
+ */
+VALUE cBN;
+VALUE eBNError;
+
+/*
+ * Public
+ */
+VALUE
+ossl_bn_new(BIGNUM *bn)
+{
+ BIGNUM *newbn;
+ VALUE obj;
+
+ newbn = bn ? BN_dup(bn) : BN_new();
+ if (!newbn) {
+ ossl_raise(eBNError, NULL);
+ }
+ WrapBN(cBN, obj, newbn);
+
+ return obj;
+}
+
+BIGNUM *
+GetBNPtr(VALUE obj)
+{
+ BIGNUM *bn = NULL;
+
+ if (RTEST(rb_obj_is_kind_of(obj, cBN))) {
+ GetBN(obj, bn);
+ } else switch (TYPE(obj)) {
+ case T_FIXNUM:
+ case T_BIGNUM:
+ obj = rb_String(obj);
+ if (!BN_dec2bn(&bn, StringValuePtr(obj))) {
+ ossl_raise(eBNError, NULL);
+ }
+ WrapBN(cBN, obj, bn); /* Handle potencial mem leaks */
+ break;
+ default:
+ ossl_raise(rb_eTypeError, "Cannot convert into OpenSSL::BN");
+ }
+ return bn;
+}
+
+/*
+ * Private
+ */
+/*
+ * BN_CTX - is used in more difficult math. ops
+ * (Why just 1? Because Ruby itself isn't thread safe,
+ * we don't need to care about threads)
+ */
+BN_CTX *ossl_bn_ctx;
+
+static VALUE
+ossl_bn_alloc(VALUE klass)
+{
+ BIGNUM *bn;
+ VALUE obj;
+
+ if (!(bn = BN_new())) {
+ ossl_raise(eBNError, NULL);
+ }
+ WrapBN(klass, obj, bn);
+
+ return obj;
+}
+
+static VALUE
+ossl_bn_initialize(int argc, VALUE *argv, VALUE self)
+{
+ BIGNUM *bn;
+ VALUE str, bs;
+ int base = 10;
+
+ if (rb_scan_args(argc, argv, "11", &str, &bs) == 2) {
+ base = NUM2INT(bs);
+ }
+ StringValue(str);
+ GetBN(self, bn);
+ if (RTEST(rb_obj_is_kind_of(str, cBN))) {
+ BIGNUM *other;
+
+ GetBN(str, other); /* Safe - we checked kind_of? above */
+ if (!BN_copy(bn, other)) {
+ ossl_raise(eBNError, NULL);
+ }
+ return self;
+ }
+
+ switch (base) {
+ case 0:
+ if (!BN_mpi2bn(RSTRING(str)->ptr, RSTRING(str)->len, bn)) {
+ ossl_raise(eBNError, NULL);
+ }
+ break;
+ case 2:
+ if (!BN_bin2bn(RSTRING(str)->ptr, RSTRING(str)->len, bn)) {
+ ossl_raise(eBNError, NULL);
+ }
+ break;
+ case 10:
+ if (!BN_dec2bn(&bn, RSTRING(str)->ptr)) {
+ ossl_raise(eBNError, NULL);
+ }
+ break;
+ case 16:
+ if (!BN_hex2bn(&bn, RSTRING(str)->ptr)) {
+ ossl_raise(eBNError, NULL);
+ }
+ break;
+ default:
+ ossl_raise(rb_eArgError, "illegal radix %d", base);
+ }
+ return self;
+}
+
+static VALUE
+ossl_bn_to_s(int argc, VALUE *argv, VALUE self)
+{
+ BIGNUM *bn;
+ VALUE str, bs;
+ int base = 10, len;
+ char *buf;
+
+ if (rb_scan_args(argc, argv, "01", &bs) == 1) {
+ base = NUM2INT(bs);
+ }
+ GetBN(self, bn);
+ switch (base) {
+ case 0:
+ len = BN_bn2mpi(bn, NULL);
+ 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);
+ 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);
+ str = ossl_buf2str(buf, strlen(buf));
+ break;
+ case 16:
+ 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);
+ }
+
+ return str;
+}
+
+static VALUE
+ossl_bn_to_i(VALUE self)
+{
+ BIGNUM *bn;
+ char *txt;
+ VALUE num;
+
+ GetBN(self, bn);
+
+ if (!(txt = BN_bn2dec(bn))) {
+ ossl_raise(eBNError, NULL);
+ }
+ num = rb_cstr_to_inum(txt, 10, Qtrue);
+ OPENSSL_free(txt);
+
+ return num;
+}
+
+static VALUE
+ossl_bn_to_bn(VALUE self)
+{
+ return self;
+}
+
+static VALUE
+ossl_bn_coerce(VALUE self, VALUE other)
+{
+ switch(TYPE(other)) {
+ case T_STRING:
+ self = ossl_bn_to_s(0, NULL, self);
+ break;
+ case T_FIXNUM:
+ case T_BIGNUM:
+ self = ossl_bn_to_i(self);
+ break;
+ default:
+ if (!RTEST(rb_obj_is_kind_of(other, cBN))) {
+ ossl_raise(rb_eTypeError, "Don't know how to coerce");
+ }
+ }
+ return rb_assoc_new(other, self);
+}
+
+#define BIGNUM_BOOL1(func) \
+ static VALUE \
+ ossl_bn_##func(VALUE self) \
+ { \
+ BIGNUM *bn; \
+ GetBN(self, bn); \
+ if (BN_##func(bn)) { \
+ return Qtrue; \
+ } \
+ return Qfalse; \
+ }
+BIGNUM_BOOL1(is_zero);
+BIGNUM_BOOL1(is_one);
+BIGNUM_BOOL1(is_odd);
+
+#define BIGNUM_1c(func) \
+ static VALUE \
+ ossl_bn_##func(VALUE self) \
+ { \
+ BIGNUM *bn, *result; \
+ VALUE obj; \
+ GetBN(self, bn); \
+ if (!(result = BN_new())) { \
+ ossl_raise(eBNError, NULL); \
+ } \
+ if (!BN_##func(result, bn, ossl_bn_ctx)) { \
+ BN_free(result); \
+ ossl_raise(eBNError, NULL); \
+ } \
+ WrapBN(CLASS_OF(self), obj, result); \
+ return obj; \
+ }
+BIGNUM_1c(sqr);
+
+#define BIGNUM_2(func) \
+ static VALUE \
+ ossl_bn_##func(VALUE self, VALUE other) \
+ { \
+ BIGNUM *bn1, *bn2 = GetBNPtr(other), *result; \
+ VALUE obj; \
+ GetBN(self, bn1); \
+ if (!(result = BN_new())) { \
+ ossl_raise(eBNError, NULL); \
+ } \
+ if (!BN_##func(result, bn1, bn2)) { \
+ BN_free(result); \
+ ossl_raise(eBNError, NULL); \
+ } \
+ WrapBN(CLASS_OF(self), obj, result); \
+ return obj; \
+ }
+BIGNUM_2(add);
+BIGNUM_2(sub);
+
+#define BIGNUM_2c(func) \
+ static VALUE \
+ ossl_bn_##func(VALUE self, VALUE other) \
+ { \
+ BIGNUM *bn1, *bn2 = GetBNPtr(other), *result; \
+ VALUE obj; \
+ GetBN(self, bn1); \
+ if (!(result = BN_new())) { \
+ ossl_raise(eBNError, NULL); \
+ } \
+ if (!BN_##func(result, bn1, bn2, ossl_bn_ctx)) { \
+ BN_free(result); \
+ ossl_raise(eBNError, NULL); \
+ } \
+ WrapBN(CLASS_OF(self), obj, result); \
+ return obj; \
+ }
+BIGNUM_2c(mul);
+BIGNUM_2c(mod);
+BIGNUM_2c(exp);
+BIGNUM_2c(gcd);
+BIGNUM_2c(mod_sqr);
+BIGNUM_2c(mod_inverse);
+
+static VALUE
+ossl_bn_div(VALUE self, VALUE other)
+{
+ BIGNUM *bn1, *bn2 = GetBNPtr(other), *r1, *r2;
+ VALUE obj1, obj2;
+
+ GetBN(self, bn1);
+
+ if (!(r1 = BN_new())) {
+ ossl_raise(eBNError, NULL);
+ }
+ if (!(r2 = BN_new())) {
+ BN_free(r1);
+ ossl_raise(eBNError, NULL);
+ }
+ if (!BN_div(r1, r2, bn1, bn2, ossl_bn_ctx)) {
+ BN_free(r1);
+ BN_free(r2);
+ ossl_raise(eBNError, NULL);
+ }
+ WrapBN(CLASS_OF(self), obj1, r1);
+ WrapBN(CLASS_OF(self), obj2, r2);
+
+ return rb_ary_new3(2, obj1, obj2);
+}
+
+#define BIGNUM_3c(func) \
+ static VALUE \
+ ossl_bn_##func(VALUE self, VALUE other1, VALUE other2) \
+ { \
+ BIGNUM *bn1, *bn2 = GetBNPtr(other1); \
+ BIGNUM *bn3 = GetBNPtr(other2), *result; \
+ VALUE obj; \
+ GetBN(self, bn1); \
+ if (!(result = BN_new())) { \
+ ossl_raise(eBNError, NULL); \
+ } \
+ if (!BN_##func(result, bn1, bn2, bn3, ossl_bn_ctx)) { \
+ BN_free(result); \
+ ossl_raise(eBNError, NULL); \
+ } \
+ WrapBN(CLASS_OF(self), obj, result); \
+ return obj; \
+ }
+BIGNUM_3c(mod_add);
+BIGNUM_3c(mod_sub);
+BIGNUM_3c(mod_mul);
+BIGNUM_3c(mod_exp);
+
+#define BIGNUM_BIT(func) \
+ static VALUE \
+ ossl_bn_##func(VALUE self, VALUE bit) \
+ { \
+ BIGNUM *bn; \
+ GetBN(self, bn); \
+ if (!BN_##func(bn, NUM2INT(bit))) { \
+ ossl_raise(eBNError, NULL); \
+ } \
+ return self; \
+ }
+BIGNUM_BIT(set_bit);
+BIGNUM_BIT(clear_bit);
+BIGNUM_BIT(mask_bits);
+
+static VALUE
+ossl_bn_is_bit_set(VALUE self, VALUE bit)
+{
+ int b;
+ BIGNUM *bn;
+
+ b = NUM2INT(bit);
+ GetBN(self, bn);
+ if (BN_is_bit_set(bn, b)) {
+ return Qtrue;
+ }
+ return Qfalse;
+}
+
+#define BIGNUM_SHIFT(func) \
+ static VALUE \
+ ossl_bn_##func(VALUE self, VALUE bits) \
+ { \
+ BIGNUM *bn, *result; \
+ int b; \
+ VALUE obj; \
+ b = NUM2INT(bits); \
+ GetBN(self, bn); \
+ if (!(result = BN_new())) { \
+ ossl_raise(eBNError, NULL); \
+ } \
+ if (!BN_##func(result, bn, b)) { \
+ BN_free(result); \
+ ossl_raise(eBNError, NULL); \
+ } \
+ WrapBN(CLASS_OF(self), obj, result); \
+ return obj; \
+ }
+BIGNUM_SHIFT(lshift);
+BIGNUM_SHIFT(rshift);
+
+#define BIGNUM_RAND(func) \
+ static VALUE \
+ ossl_bn_s_##func(int argc, VALUE *argv, VALUE klass) \
+ { \
+ BIGNUM *result; \
+ int bottom = 0, top = 0, b; \
+ VALUE bits, fill, odd, obj; \
+ \
+ switch (rb_scan_args(argc, argv, "12", &bits, &fill, &odd)) { \
+ case 3: \
+ bottom = (odd == Qtrue) ? 1 : 0; \
+ /* FALLTHROUGH */ \
+ case 2: \
+ top = FIX2INT(fill); \
+ } \
+ b = NUM2INT(bits); \
+ if (!(result = BN_new())) { \
+ ossl_raise(eBNError, NULL); \
+ } \
+ if (!BN_##func(result, b, top, bottom)) { \
+ BN_free(result); \
+ ossl_raise(eBNError, NULL); \
+ } \
+ WrapBN(klass, obj, result); \
+ return obj; \
+ }
+BIGNUM_RAND(rand);
+BIGNUM_RAND(pseudo_rand);
+
+#define BIGNUM_RAND_RANGE(func) \
+ static VALUE \
+ ossl_bn_s_##func##_range(VALUE klass, VALUE range) \
+ { \
+ BIGNUM *bn = GetBNPtr(range), *result; \
+ VALUE obj; \
+ if (!(result = BN_new())) { \
+ ossl_raise(eBNError, NULL); \
+ } \
+ if (!BN_##func##_range(result, bn)) { \
+ BN_free(result); \
+ ossl_raise(eBNError, NULL); \
+ } \
+ WrapBN(klass, obj, result); \
+ return obj; \
+ }
+BIGNUM_RAND_RANGE(rand);
+BIGNUM_RAND_RANGE(pseudo_rand);
+
+static VALUE
+ossl_bn_s_generate_prime(int argc, VALUE *argv, VALUE klass)
+{
+ BIGNUM *add = NULL, *rem = NULL, *result;
+ int safe = 1, num;
+ VALUE vnum, vsafe, vadd, vrem, obj;
+
+ rb_scan_args(argc, argv, "13", &vnum, &vsafe, &vadd, &vrem);
+
+ num = NUM2INT(vnum);
+
+ if (vsafe == Qfalse) {
+ safe = 0;
+ }
+ if (!NIL_P(vadd)) {
+ if (NIL_P(vrem)) {
+ ossl_raise(rb_eArgError,
+ "if ADD is specified, REM must be also given");
+ }
+ add = GetBNPtr(vadd);
+ rem = GetBNPtr(vrem);
+ }
+ if (!(result = BN_new())) {
+ ossl_raise(eBNError, NULL);
+ }
+ if (!BN_generate_prime(result, num, safe, add, rem, NULL, NULL)) {
+ BN_free(result);
+ ossl_raise(eBNError, NULL);
+ }
+ WrapBN(klass, obj, result);
+
+ return obj;
+}
+
+#define BIGNUM_NUM(func) \
+ static VALUE \
+ ossl_bn_##func(VALUE self) \
+ { \
+ BIGNUM *bn; \
+ GetBN(self, bn); \
+ return INT2FIX(BN_##func(bn)); \
+ }
+BIGNUM_NUM(num_bytes);
+BIGNUM_NUM(num_bits);
+
+static VALUE
+ossl_bn_copy(VALUE self, VALUE other)
+{
+ BIGNUM *bn1, *bn2;
+
+ rb_check_frozen(self);
+
+ if (self == other) return self;
+
+ GetBN(self, bn1);
+ bn2 = GetBNPtr(other);
+
+ if (!BN_copy(bn1, bn2)) {
+ ossl_raise(eBNError, NULL);
+ }
+ return self;
+}
+
+#define BIGNUM_CMP(func) \
+ static VALUE \
+ ossl_bn_##func(VALUE self, VALUE other) \
+ { \
+ BIGNUM *bn1, *bn2 = GetBNPtr(other); \
+ GetBN(self, bn1); \
+ return INT2FIX(BN_##func(bn1, bn2)); \
+ }
+BIGNUM_CMP(cmp);
+BIGNUM_CMP(ucmp);
+
+static VALUE
+ossl_bn_eql(VALUE self, VALUE other)
+{
+ if (ossl_bn_cmp(self, other) == INT2FIX(0)) {
+ return Qtrue;
+ }
+ return Qfalse;
+}
+
+static VALUE
+ossl_bn_is_prime(int argc, VALUE *argv, VALUE self)
+{
+ BIGNUM *bn;
+ VALUE vchecks;
+ int checks = BN_prime_checks;
+
+ if (rb_scan_args(argc, argv, "01", &vchecks) == 0) {
+ checks = NUM2INT(vchecks);
+ }
+ GetBN(self, bn);
+ switch (BN_is_prime(bn, checks, NULL, ossl_bn_ctx, NULL)) {
+ case 1:
+ return Qtrue;
+ case 0:
+ return Qfalse;
+ default:
+ ossl_raise(eBNError, NULL);
+ }
+ /* not reachable */
+ return Qnil;
+}
+
+static VALUE
+ossl_bn_is_prime_fasttest(int argc, VALUE *argv, VALUE self)
+{
+ BIGNUM *bn;
+ VALUE vchecks, vtrivdiv;
+ int checks = BN_prime_checks, do_trial_division = 1;
+
+ rb_scan_args(argc, argv, "02", &vchecks, &vtrivdiv);
+
+ if (!NIL_P(vchecks)) {
+ checks = NUM2INT(vchecks);
+ }
+ GetBN(self, bn);
+ /* handle true/false */
+ if (vtrivdiv == Qfalse) {
+ do_trial_division = 0;
+ }
+ switch (BN_is_prime_fasttest(bn, checks, NULL, ossl_bn_ctx, NULL, do_trial_division)) {
+ case 1:
+ return Qtrue;
+ case 0:
+ return Qfalse;
+ default:
+ ossl_raise(eBNError, NULL);
+ }
+ /* not reachable */
+ return Qnil;
+}
+
+/*
+ * INIT
+ * (NOTE: ordering of methods is the same as in 'man bn')
+ */
+void
+Init_ossl_bn()
+{
+ if (!(ossl_bn_ctx = BN_CTX_new())) {
+ ossl_raise(rb_eRuntimeError, "Cannot init BN_CTX");
+ }
+
+ eBNError = rb_define_class_under(mOSSL, "BNError", eOSSLError);
+
+ cBN = rb_define_class_under(mOSSL, "BN", rb_cObject);
+
+ rb_define_alloc_func(cBN, ossl_bn_alloc);
+ rb_define_method(cBN, "initialize", ossl_bn_initialize, -1);
+
+ rb_define_copy_func(cBN, ossl_bn_copy);
+ rb_define_method(cBN, "copy", ossl_bn_copy, 1);
+
+ /* swap (=coerce?) */
+
+ rb_define_method(cBN, "num_bytes", ossl_bn_num_bytes, 0);
+ rb_define_method(cBN, "num_bits", ossl_bn_num_bits, 0);
+ /* num_bits_word */
+
+ rb_define_method(cBN, "+", ossl_bn_add, 1);
+ rb_define_method(cBN, "-", ossl_bn_sub, 1);
+ rb_define_method(cBN, "*", ossl_bn_mul, 1);
+ rb_define_method(cBN, "sqr", ossl_bn_sqr, 0);
+ rb_define_method(cBN, "/", ossl_bn_div, 1);
+ rb_define_method(cBN, "%", ossl_bn_mod, 1);
+ /* nnmod */
+
+ rb_define_method(cBN, "mod_add", ossl_bn_mod_add, 2);
+ rb_define_method(cBN, "mod_sub", ossl_bn_mod_sub, 2);
+ rb_define_method(cBN, "mod_mul", ossl_bn_mod_mul, 2);
+ rb_define_method(cBN, "mod_sqr", ossl_bn_mod_sqr, 1);
+ rb_define_method(cBN, "**", ossl_bn_exp, 1);
+ rb_define_method(cBN, "mod_exp", ossl_bn_mod_exp, 2);
+ rb_define_method(cBN, "gcd", ossl_bn_gcd, 1);
+
+ /* add_word
+ * sub_word
+ * mul_word
+ * div_word
+ * mod_word */
+
+ rb_define_method(cBN, "cmp", ossl_bn_cmp, 1);
+ rb_define_alias(cBN, "<=>", "cmp");
+ rb_define_method(cBN, "ucmp", ossl_bn_ucmp, 1);
+ rb_define_method(cBN, "eql?", ossl_bn_eql, 1);
+ rb_define_alias(cBN, "==", "eql?");
+ rb_define_alias(cBN, "===", "eql?");
+ rb_define_method(cBN, "zero?", ossl_bn_is_zero, 0);
+ rb_define_method(cBN, "one?", ossl_bn_is_one, 0);
+ /* is_word */
+ rb_define_method(cBN, "odd?", ossl_bn_is_odd, 0);
+
+ /* zero
+ * one
+ * value_one - DON'T IMPL.
+ * set_word
+ * get_word */
+
+ rb_define_singleton_method(cBN, "rand", ossl_bn_s_rand, -1);
+ rb_define_singleton_method(cBN, "pseudo_rand", ossl_bn_s_pseudo_rand, -1);
+ rb_define_singleton_method(cBN, "rand_range", ossl_bn_s_rand_range, 1);
+ rb_define_singleton_method(cBN, "pseudo_rand_range", ossl_bn_s_pseudo_rand_range, 1);
+
+ rb_define_singleton_method(cBN, "generate_prime", ossl_bn_s_generate_prime, -1);
+ rb_define_method(cBN, "prime?", ossl_bn_is_prime, -1);
+
+ rb_define_method(cBN, "set_bit!", ossl_bn_set_bit, 1);
+ rb_define_method(cBN, "clear_bit!", ossl_bn_clear_bit, 1);
+ rb_define_method(cBN, "bit_set?", ossl_bn_is_bit_set, 1);
+ rb_define_method(cBN, "mask_bits!", ossl_bn_mask_bits, 1);
+ rb_define_method(cBN, "<<", ossl_bn_lshift, 1);
+ /* lshift1 - DON'T IMPL. */
+ rb_define_method(cBN, ">>", ossl_bn_rshift, 1);
+ /* rshift1 - DON'T IMPL. */
+
+ /*
+ * bn2bin
+ * bin2bn
+ * bn2hex
+ * bn2dec
+ * hex2bn
+ * dec2bn - all these are implemented in ossl_bn_initialize, and ossl_bn_to_s
+ * print - NOT IMPL.
+ * print_fp - NOT IMPL.
+ * bn2mpi
+ * mpi2bn
+ */
+ rb_define_method(cBN, "to_s", ossl_bn_to_s, -1);
+ rb_define_method(cBN, "to_i", ossl_bn_to_i, 0);
+ rb_define_alias(cBN, "to_int", "to_i");
+ rb_define_method(cBN, "to_bn", ossl_bn_to_bn, 0);
+ rb_define_method(cBN, "coerce", ossl_bn_coerce, 1);
+
+ /*
+ * TODO:
+ * But how to: from_bin, from_mpi? PACK?
+ * to_bin
+ * to_mpi
+ */
+
+ rb_define_method(cBN, "mod_inverse", ossl_bn_mod_inverse, 1);
+
+ /* RECiProcal
+ * MONTgomery */
+
+ /*
+ * TODO:
+ * Where to belong these?
+ */
+ rb_define_method(cBN, "prime_fasttest?", ossl_bn_is_prime_fasttest, -1);
+}
+
diff --git a/ruby_1_8_5/ext/openssl/ossl_bn.h b/ruby_1_8_5/ext/openssl/ossl_bn.h
new file mode 100644
index 0000000000..bccdbc0cd6
--- /dev/null
+++ b/ruby_1_8_5/ext/openssl/ossl_bn.h
@@ -0,0 +1,22 @@
+/*
+ * $Id: ossl_bn.h,v 1.1 2003/07/23 16:11:29 gotoyuzo Exp $
+ * '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_BN_H_)
+#define _OSSL_BN_H_
+
+extern VALUE cBN;
+extern VALUE eBNError;
+
+VALUE ossl_bn_new(BIGNUM *);
+BIGNUM *GetBNPtr(VALUE);
+void Init_ossl_bn(void);
+
+#endif /* _OSS_BN_H_ */
+
diff --git a/ruby_1_8_5/ext/openssl/ossl_cipher.c b/ruby_1_8_5/ext/openssl/ossl_cipher.c
new file mode 100644
index 0000000000..8d96d0b35a
--- /dev/null
+++ b/ruby_1_8_5/ext/openssl/ossl_cipher.c
@@ -0,0 +1,406 @@
+/*
+ * $Id: ossl_cipher.c,v 1.4.2.6 2006/06/20 11:18:15 gotoyuzo Exp $
+ * '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'.)
+ */
+#include "ossl.h"
+
+#define MakeCipher(obj, klass, ctx) \
+ obj = Data_Make_Struct(klass, EVP_CIPHER_CTX, 0, ossl_cipher_free, ctx)
+#define GetCipher(obj, ctx) do { \
+ Data_Get_Struct(obj, EVP_CIPHER_CTX, ctx); \
+ if (!ctx) { \
+ ossl_raise(rb_eRuntimeError, "Cipher not inititalized!"); \
+ } \
+} while (0)
+#define SafeGetCipher(obj, ctx) do { \
+ OSSL_Check_Kind(obj, cCipher); \
+ GetCipher(obj, ctx); \
+} while (0)
+
+/*
+ * Classes
+ */
+VALUE mCipher;
+VALUE cCipher;
+VALUE eCipherError;
+
+static VALUE ossl_cipher_alloc(VALUE klass);
+
+/*
+ * PUBLIC
+ */
+const EVP_CIPHER *
+GetCipherPtr(VALUE obj)
+{
+ EVP_CIPHER_CTX *ctx;
+
+ SafeGetCipher(obj, ctx);
+
+ return EVP_CIPHER_CTX_cipher(ctx);
+}
+
+VALUE
+ossl_cipher_new(const EVP_CIPHER *cipher)
+{
+ VALUE ret;
+ EVP_CIPHER_CTX *ctx;
+
+ ret = ossl_cipher_alloc(cCipher);
+ GetCipher(ret, ctx);
+ EVP_CIPHER_CTX_init(ctx);
+ if (EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, -1) != 1)
+ ossl_raise(eCipherError, NULL);
+
+ return ret;
+}
+
+/*
+ * PRIVATE
+ */
+static void
+ossl_cipher_free(EVP_CIPHER_CTX *ctx)
+{
+ if (ctx) {
+ EVP_CIPHER_CTX_cleanup(ctx);
+ free(ctx);
+ }
+}
+
+static VALUE
+ossl_cipher_alloc(VALUE klass)
+{
+ EVP_CIPHER_CTX *ctx;
+ VALUE obj;
+
+ MakeCipher(obj, klass, ctx);
+ EVP_CIPHER_CTX_init(ctx);
+
+ return obj;
+}
+
+static VALUE
+ossl_cipher_initialize(VALUE self, VALUE str)
+{
+ EVP_CIPHER_CTX *ctx;
+ const EVP_CIPHER *cipher;
+ char *name;
+
+ name = StringValuePtr(str);
+ GetCipher(self, ctx);
+ if (!(cipher = EVP_get_cipherbyname(name))) {
+ ossl_raise(rb_eRuntimeError, "unsupported cipher algorithm (%s)", name);
+ }
+ if (EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, -1) != 1)
+ ossl_raise(eCipherError, NULL);
+
+ return self;
+}
+static VALUE
+ossl_cipher_copy(VALUE self, VALUE other)
+{
+ EVP_CIPHER_CTX *ctx1, *ctx2;
+
+ rb_check_frozen(self);
+ if (self == other) return self;
+
+ GetCipher(self, ctx1);
+ SafeGetCipher(other, ctx2);
+ if (EVP_CIPHER_CTX_copy(ctx1, ctx2) != 1)
+ ossl_raise(eCipherError, NULL);
+
+ return self;
+}
+
+static void*
+add_cipher_name_to_ary(const OBJ_NAME *name, VALUE ary)
+{
+ rb_ary_push(ary, rb_str_new2(name->name));
+ return NULL;
+}
+
+static VALUE
+ossl_s_ciphers(VALUE self)
+{
+#ifdef HAVE_OBJ_NAME_DO_ALL_SORTED
+ VALUE ary;
+
+ ary = rb_ary_new();
+ OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_CIPHER_METH,
+ (void(*)(const OBJ_NAME*,void*))add_cipher_name_to_ary,
+ (void*)ary);
+
+ return ary;
+#else
+ rb_notimplement();
+#endif
+}
+
+static VALUE
+ossl_cipher_reset(VALUE self)
+{
+ EVP_CIPHER_CTX *ctx;
+
+ GetCipher(self, ctx);
+ if (EVP_CipherInit_ex(ctx, NULL, NULL, NULL, NULL, -1) != 1)
+ ossl_raise(eCipherError, NULL);
+
+ return self;
+}
+
+static VALUE
+ossl_cipher_init(int argc, VALUE *argv, VALUE self, int mode)
+{
+ EVP_CIPHER_CTX *ctx;
+ unsigned char key[EVP_MAX_KEY_LENGTH], *p_key = NULL;
+ unsigned char iv[EVP_MAX_IV_LENGTH], *p_iv = NULL;
+ VALUE pass, init_v;
+
+ if(rb_scan_args(argc, argv, "02", &pass, &init_v) > 0){
+ /*
+ * oops. this code mistakes salt for IV.
+ * We deprecated the arguments for this method, but we decided
+ * keeping this behaviour for backward compatibility.
+ */
+ StringValue(pass);
+ GetCipher(self, ctx);
+ if (NIL_P(init_v)) memcpy(iv, "OpenSSL for Ruby rulez!", sizeof(iv));
+ else{
+ char *cname = rb_class2name(rb_obj_class(self));
+ rb_warning("key derivation by %s#encrypt is deprecated; "
+ "use %s::pkcs5_keyivgen instead", cname, cname);
+ StringValue(init_v);
+ if (EVP_MAX_IV_LENGTH > RSTRING(init_v)->len) {
+ memset(iv, 0, EVP_MAX_IV_LENGTH);
+ memcpy(iv, RSTRING(init_v)->ptr, RSTRING(init_v)->len);
+ }
+ else memcpy(iv, RSTRING(init_v)->ptr, sizeof(iv));
+ }
+ EVP_BytesToKey(EVP_CIPHER_CTX_cipher(ctx), EVP_md5(), iv,
+ RSTRING(pass)->ptr, RSTRING(pass)->len, 1, key, NULL);
+ p_key = key;
+ p_iv = iv;
+ }
+ else {
+ GetCipher(self, ctx);
+ }
+ if (EVP_CipherInit_ex(ctx, NULL, NULL, p_key, p_iv, mode) != 1) {
+ ossl_raise(eCipherError, NULL);
+ }
+
+ return self;
+}
+
+static VALUE
+ossl_cipher_encrypt(int argc, VALUE *argv, VALUE self)
+{
+ return ossl_cipher_init(argc, argv, self, 1);
+}
+
+static VALUE
+ossl_cipher_decrypt(int argc, VALUE *argv, VALUE self)
+{
+ return ossl_cipher_init(argc, argv, self, 0);
+}
+
+static VALUE
+ossl_cipher_pkcs5_keyivgen(int argc, VALUE *argv, VALUE self)
+{
+ EVP_CIPHER_CTX *ctx;
+ const EVP_MD *digest;
+ VALUE vpass, vsalt, viter, vdigest;
+ unsigned char key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH], *salt = NULL;
+ int iter;
+
+ rb_scan_args(argc, argv, "13", &vpass, &vsalt, &viter, &vdigest);
+ StringValue(vpass);
+ if(!NIL_P(vsalt)){
+ StringValue(vsalt);
+ if(RSTRING(vsalt)->len != PKCS5_SALT_LEN)
+ rb_raise(eCipherError, "salt must be an 8-octet string");
+ salt = RSTRING(vsalt)->ptr;
+ }
+ iter = NIL_P(viter) ? 2048 : NUM2INT(viter);
+ digest = NIL_P(vdigest) ? EVP_md5() : GetDigestPtr(vdigest);
+ GetCipher(self, ctx);
+ EVP_BytesToKey(EVP_CIPHER_CTX_cipher(ctx), digest, salt,
+ RSTRING(vpass)->ptr, RSTRING(vpass)->len, iter, key, iv);
+ if (EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, -1) != 1)
+ ossl_raise(eCipherError, NULL);
+ OPENSSL_cleanse(key, sizeof key);
+ OPENSSL_cleanse(iv, sizeof iv);
+
+ return Qnil;
+}
+
+static VALUE
+ossl_cipher_update(VALUE self, VALUE data)
+{
+ EVP_CIPHER_CTX *ctx;
+ char *in;
+ int in_len, out_len;
+ VALUE str;
+
+ StringValue(data);
+ in = RSTRING(data)->ptr;
+ if ((in_len = RSTRING(data)->len) == 0)
+ rb_raise(rb_eArgError, "data must not be empty");
+ GetCipher(self, 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);
+ assert(out_len < RSTRING(str)->len);
+ RSTRING(str)->len = out_len;
+ RSTRING(str)->ptr[out_len] = 0;
+
+ return str;
+}
+
+static VALUE
+ossl_cipher_update_deprecated(VALUE self, VALUE data)
+{
+ char *cname;
+
+ cname = rb_class2name(rb_obj_class(self));
+ rb_warning("%s#<< is deprecated; use %s#update instead", cname, cname);
+ return ossl_cipher_update(self, data);
+}
+
+static VALUE
+ossl_cipher_final(VALUE self)
+{
+ EVP_CIPHER_CTX *ctx;
+ int out_len;
+ VALUE str;
+
+ GetCipher(self, ctx);
+ str = rb_str_new(0, EVP_CIPHER_CTX_block_size(ctx));
+ if (!EVP_CipherFinal_ex(ctx, RSTRING(str)->ptr, &out_len))
+ ossl_raise(eCipherError, NULL);
+ assert(out_len <= RSTRING(str)->len);
+ RSTRING(str)->len = out_len;
+ RSTRING(str)->ptr[out_len] = 0;
+
+ return str;
+}
+
+static VALUE
+ossl_cipher_name(VALUE self)
+{
+ EVP_CIPHER_CTX *ctx;
+
+ GetCipher(self, ctx);
+
+ return rb_str_new2(EVP_CIPHER_name(EVP_CIPHER_CTX_cipher(ctx)));
+}
+
+static VALUE
+ossl_cipher_set_key(VALUE self, VALUE key)
+{
+ EVP_CIPHER_CTX *ctx;
+
+ StringValue(key);
+ GetCipher(self, ctx);
+
+ if (RSTRING(key)->len < EVP_CIPHER_CTX_key_length(ctx))
+ ossl_raise(eCipherError, "key length too short");
+
+ if (EVP_CipherInit_ex(ctx, NULL, NULL, RSTRING(key)->ptr, NULL, -1) != 1)
+ ossl_raise(eCipherError, NULL);
+
+ return key;
+}
+
+static VALUE
+ossl_cipher_set_iv(VALUE self, VALUE iv)
+{
+ EVP_CIPHER_CTX *ctx;
+
+ StringValue(iv);
+ GetCipher(self, ctx);
+
+ if (RSTRING(iv)->len < EVP_CIPHER_CTX_iv_length(ctx))
+ ossl_raise(eCipherError, "iv length too short");
+
+ if (EVP_CipherInit_ex(ctx, NULL, NULL, NULL, RSTRING(iv)->ptr, -1) != 1)
+ ossl_raise(eCipherError, NULL);
+
+ return iv;
+}
+
+static VALUE
+ossl_cipher_set_key_length(VALUE self, VALUE key_length)
+{
+ EVP_CIPHER_CTX *ctx;
+ int len = NUM2INT(key_length);
+
+ GetCipher(self, ctx);
+ if (EVP_CIPHER_CTX_set_key_length(ctx, len) != 1)
+ ossl_raise(eCipherError, NULL);
+
+ return key_length;
+}
+
+static VALUE
+ossl_cipher_set_padding(VALUE self, VALUE padding)
+{
+#if defined(HAVE_EVP_CIPHER_CTX_SET_PADDING)
+ EVP_CIPHER_CTX *ctx;
+ int pad = NUM2INT(padding);
+
+ GetCipher(self, ctx);
+ if (EVP_CIPHER_CTX_set_padding(ctx, pad) != 1)
+ ossl_raise(eCipherError, NULL);
+#else
+ rb_notimplement();
+#endif
+ return padding;
+}
+
+#define CIPHER_0ARG_INT(func) \
+ static VALUE \
+ ossl_cipher_##func(VALUE self) \
+ { \
+ EVP_CIPHER_CTX *ctx; \
+ GetCipher(self, ctx); \
+ return INT2NUM(EVP_CIPHER_##func(EVP_CIPHER_CTX_cipher(ctx))); \
+ }
+CIPHER_0ARG_INT(key_length)
+CIPHER_0ARG_INT(iv_length)
+CIPHER_0ARG_INT(block_size)
+
+/*
+ * INIT
+ */
+void
+Init_ossl_cipher(void)
+{
+ mCipher = rb_define_module_under(mOSSL, "Cipher");
+ eCipherError = rb_define_class_under(mOSSL, "CipherError", eOSSLError);
+ cCipher = rb_define_class_under(mCipher, "Cipher", rb_cObject);
+
+ rb_define_alloc_func(cCipher, ossl_cipher_alloc);
+ rb_define_copy_func(cCipher, ossl_cipher_copy);
+ rb_define_module_function(mCipher, "ciphers", ossl_s_ciphers, 0);
+ rb_define_method(cCipher, "initialize", ossl_cipher_initialize, 1);
+ rb_define_method(cCipher, "reset", ossl_cipher_reset, 0);
+ rb_define_method(cCipher, "encrypt", ossl_cipher_encrypt, -1);
+ rb_define_method(cCipher, "decrypt", ossl_cipher_decrypt, -1);
+ rb_define_method(cCipher, "pkcs5_keyivgen", ossl_cipher_pkcs5_keyivgen, -1);
+ rb_define_method(cCipher, "update", ossl_cipher_update, 1);
+ rb_define_method(cCipher, "<<", ossl_cipher_update_deprecated, 1);
+ rb_define_method(cCipher, "final", ossl_cipher_final, 0);
+ rb_define_method(cCipher, "name", ossl_cipher_name, 0);
+ rb_define_method(cCipher, "key=", ossl_cipher_set_key, 1);
+ rb_define_method(cCipher, "key_len=", ossl_cipher_set_key_length, 1);
+ rb_define_method(cCipher, "key_len", ossl_cipher_key_length, 0);
+ rb_define_method(cCipher, "iv=", ossl_cipher_set_iv, 1);
+ rb_define_method(cCipher, "iv_len", ossl_cipher_iv_length, 0);
+ rb_define_method(cCipher, "block_size", ossl_cipher_block_size, 0);
+ rb_define_method(cCipher, "padding=", ossl_cipher_set_padding, 1);
+}
diff --git a/ruby_1_8_5/ext/openssl/ossl_cipher.h b/ruby_1_8_5/ext/openssl/ossl_cipher.h
new file mode 100644
index 0000000000..870927c37c
--- /dev/null
+++ b/ruby_1_8_5/ext/openssl/ossl_cipher.h
@@ -0,0 +1,23 @@
+/*
+ * $Id: ossl_cipher.h,v 1.2 2003/09/05 09:08:40 gotoyuzo Exp $
+ * '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_CIPHER_H_)
+#define _OSSL_CIPHER_H_
+
+extern VALUE mCipher;
+extern VALUE cCipher;
+extern VALUE eCipherError;
+
+const EVP_CIPHER *GetCipherPtr(VALUE);
+VALUE ossl_cipher_new(const EVP_CIPHER *);
+void Init_ossl_cipher(void);
+
+#endif /* _OSSL_CIPHER_H_ */
+
diff --git a/ruby_1_8_5/ext/openssl/ossl_config.c b/ruby_1_8_5/ext/openssl/ossl_config.c
new file mode 100644
index 0000000000..64998bb86a
--- /dev/null
+++ b/ruby_1_8_5/ext/openssl/ossl_config.c
@@ -0,0 +1,462 @@
+/*
+ * $Id: ossl_config.c,v 1.8.2.3 2004/12/15 01:54:39 matz Exp $
+ * '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'.)
+ */
+#include "ossl.h"
+
+#define WrapConfig(klass, obj, conf) do { \
+ if (!conf) { \
+ ossl_raise(rb_eRuntimeError, "Config wasn't intitialized!"); \
+ } \
+ obj = Data_Wrap_Struct(klass, 0, NCONF_free, conf); \
+} while (0)
+#define GetConfig(obj, conf) do { \
+ Data_Get_Struct(obj, CONF, conf); \
+ if (!conf) { \
+ ossl_raise(rb_eRuntimeError, "Config wasn't intitialized!"); \
+ } \
+} while (0)
+#define SafeGetConfig(obj, conf) do { \
+ OSSL_Check_Kind(obj, cConfig); \
+ GetConfig(obj, conf); \
+} while(0);
+
+/*
+ * Classes
+ */
+VALUE cConfig;
+VALUE eConfigError;
+
+/*
+ * Public
+ */
+
+static CONF *parse_config(VALUE, CONF*);
+
+CONF *
+GetConfigPtr(VALUE obj)
+{
+ CONF *conf;
+
+ SafeGetConfig(obj, conf);
+
+ return conf;
+}
+
+CONF *
+DupConfigPtr(VALUE obj)
+{
+ VALUE str;
+
+ OSSL_Check_Kind(obj, cConfig);
+ str = rb_funcall(obj, rb_intern("to_s"), 0);
+
+ return parse_config(str, NULL);
+}
+
+/*
+ * Private
+ */
+static CONF *
+parse_config(VALUE str, CONF *dst)
+{
+ CONF *conf;
+ BIO *bio;
+ long eline = -1;
+
+ bio = ossl_obj2bio(str);
+ conf = dst ? dst : NCONF_new(NULL);
+ if(!conf){
+ BIO_free(bio);
+ ossl_raise(eConfigError, NULL);
+ }
+ if(!NCONF_load_bio(conf, bio, &eline)){
+ BIO_free(bio);
+ if(!dst) NCONF_free(conf);
+ if (eline <= 0) ossl_raise(eConfigError, "wrong config format");
+ else ossl_raise(eConfigError, "error in line %d", eline);
+ ossl_raise(eConfigError, NULL);
+ }
+ BIO_free(bio);
+
+ return conf;
+}
+
+static VALUE
+ossl_config_s_parse(VALUE klass, VALUE str)
+{
+ CONF *conf;
+ VALUE obj;
+
+ conf = parse_config(str, NULL);
+ WrapConfig(klass, obj, conf);
+
+ return obj;
+}
+
+static VALUE
+ossl_config_s_alloc(VALUE klass)
+{
+ CONF *conf;
+ VALUE obj;
+
+ if(!(conf = NCONF_new(NULL)))
+ ossl_raise(eConfigError, NULL);
+ WrapConfig(klass, obj, conf);
+
+ return obj;
+}
+
+static VALUE
+ossl_config_copy(VALUE self, VALUE other)
+{
+ VALUE str;
+ CONF *conf;
+
+ str = rb_funcall(self, rb_intern("to_s"), 0);
+ GetConfig(other, conf);
+ parse_config(str, conf);
+
+ return self;
+}
+
+static VALUE
+ossl_config_initialize(int argc, VALUE *argv, VALUE self)
+{
+ CONF *conf;
+ long eline = -1;
+ char *filename;
+ VALUE path;
+
+ rb_scan_args(argc, argv, "01", &path);
+ if(!NIL_P(path)){
+ SafeStringValue(path);
+ filename = StringValuePtr(path);
+ GetConfig(self, conf);
+ if (!NCONF_load(conf, filename, &eline)){
+ if (eline <= 0)
+ ossl_raise(eConfigError, "wrong config file %s", filename);
+ else
+ ossl_raise(eConfigError, "error in %s:%d", filename, eline);
+ }
+ }
+#ifdef OSSL_NO_CONF_API
+ else rb_raise(rb_eArgError, "wrong number of arguments (0 for 1)");
+#else
+ else {
+ GetConfig(self, conf);
+ _CONF_new_data(conf);
+ }
+#endif
+
+ return self;
+}
+
+static VALUE
+ossl_config_add_value(VALUE self, VALUE section, VALUE name, VALUE value)
+{
+#ifdef OSSL_NO_CONF_API
+ rb_notimplement();
+#else
+ CONF *conf;
+ CONF_VALUE *sv, *cv;
+
+ StringValue(section);
+ StringValue(name);
+ StringValue(value);
+ GetConfig(self, conf);
+ if(!(sv = _CONF_get_section(conf, RSTRING(section)->ptr))){
+ if(!(sv = _CONF_new_section(conf, RSTRING(section)->ptr))){
+ ossl_raise(eConfigError, NULL);
+ }
+ }
+ if(!(cv = OPENSSL_malloc(sizeof(CONF_VALUE)))){
+ ossl_raise(eConfigError, NULL);
+ }
+ cv->name = BUF_strdup(RSTRING(name)->ptr);
+ cv->value = BUF_strdup(RSTRING(value)->ptr);
+ if(!cv->name || !cv->value || !_CONF_add_string(conf, sv, cv)){
+ OPENSSL_free(cv->name);
+ OPENSSL_free(cv->value);
+ OPENSSL_free(cv);
+ ossl_raise(eConfigError, "_CONF_add_string failure");
+ }
+
+ return value;
+#endif
+}
+
+static VALUE
+ossl_config_get_value(VALUE self, VALUE section, VALUE name)
+{
+ CONF *conf;
+ char *str;
+
+ StringValue(section);
+ StringValue(name);
+ GetConfig(self, conf);
+ str = NCONF_get_string(conf, RSTRING(section)->ptr, RSTRING(name)->ptr);
+ if(!str){
+ ERR_clear_error();
+ return Qnil;
+ }
+
+ return rb_str_new2(str);
+}
+
+static VALUE
+ossl_config_get_value_old(int argc, VALUE *argv, VALUE self)
+{
+ VALUE section, name;
+
+ rb_scan_args(argc, argv, "11", &section, &name);
+
+ /* support conf.value(nil, "HOME") -> conf.get_value("", "HOME") */
+ if (NIL_P(section)) section = rb_str_new2("");
+ /* support conf.value("HOME") -> conf.get_value("", "HOME") */
+ if (NIL_P(name)) {
+ name = section;
+ section = rb_str_new2("");
+ }
+ /* NOTE: Don't care about conf.get_value(nil, nil) */
+ rb_warn("Config#value is deprecated; use Config#get_value");
+ return ossl_config_get_value(self, section, name);
+}
+
+static VALUE
+set_conf_section_i(VALUE i, VALUE *arg)
+{
+ VALUE name, value;
+
+ Check_Type(i, T_ARRAY);
+ name = rb_ary_entry(i, 0);
+ value = rb_ary_entry(i, 1);
+ ossl_config_add_value(arg[0], arg[1], name, value);
+
+ return Qnil;
+}
+
+static VALUE
+ossl_config_set_section(VALUE self, VALUE section, VALUE hash)
+{
+ VALUE arg[2];
+
+ arg[0] = self;
+ arg[1] = section;
+ rb_iterate(rb_each, hash, set_conf_section_i, (VALUE)arg);
+ return hash;
+}
+
+/*
+ * Get all numbers as strings - use str.to_i to convert
+ * long number = CONF_get_number(confp->config, sect, StringValuePtr(item));
+ */
+static VALUE
+ossl_config_get_section(VALUE self, VALUE section)
+{
+ CONF *conf;
+ STACK_OF(CONF_VALUE) *sk;
+ CONF_VALUE *entry;
+ int i, entries;
+ VALUE hash;
+
+ hash = rb_hash_new();
+ StringValue(section);
+ GetConfig(self, conf);
+ if (!(sk = NCONF_get_section(conf, StringValuePtr(section)))) {
+ ERR_clear_error();
+ return hash;
+ }
+ if ((entries = sk_CONF_VALUE_num(sk)) < 0) {
+ OSSL_Debug("# of items in section is < 0?!?");
+ return hash;
+ }
+ for (i=0; i<entries; i++) {
+ entry = sk_CONF_VALUE_value(sk, i);
+ rb_hash_aset(hash, rb_str_new2(entry->name), rb_str_new2(entry->value));
+ }
+
+ return hash;
+}
+
+static VALUE
+ossl_config_get_section_old(VALUE self, VALUE section)
+{
+ rb_warn("Config#section is deprecated; use Config#[]");
+ return ossl_config_get_section(self, section);
+}
+
+#ifdef IMPLEMENT_LHASH_DOALL_ARG_FN
+static void
+get_conf_section(CONF_VALUE *cv, VALUE ary)
+{
+ if(cv->name) return;
+ rb_ary_push(ary, rb_str_new2(cv->section));
+}
+
+static IMPLEMENT_LHASH_DOALL_ARG_FN(get_conf_section, CONF_VALUE*, VALUE);
+
+static VALUE
+ossl_config_get_sections(VALUE self)
+{
+ CONF *conf;
+ VALUE ary;
+
+ GetConfig(self, conf);
+ ary = rb_ary_new();
+ lh_doall_arg(conf->data, LHASH_DOALL_ARG_FN(get_conf_section), (void*)ary);
+
+ return ary;
+}
+
+static void
+dump_conf_value(CONF_VALUE *cv, VALUE str)
+{
+ STACK_OF(CONF_VALUE) *sk;
+ CONF_VALUE *v;
+ int i, num;
+
+ if (cv->name) return;
+ sk = (STACK_OF(CONF_VALUE)*)cv->value;
+ num = sk_CONF_VALUE_num(sk);
+ rb_str_cat2(str, "[ ");
+ rb_str_cat2(str, cv->section);
+ rb_str_cat2(str, " ]\n");
+ for(i = 0; i < num; i++){
+ v = sk_CONF_VALUE_value(sk, i);
+ rb_str_cat2(str, v->name ? v->name : "None");
+ rb_str_cat2(str, "=");
+ rb_str_cat2(str, v->value ? v->value : "None");
+ rb_str_cat2(str, "\n");
+ }
+ rb_str_cat2(str, "\n");
+}
+
+static IMPLEMENT_LHASH_DOALL_ARG_FN(dump_conf_value, CONF_VALUE*, VALUE);
+
+static VALUE
+dump_conf(CONF *conf)
+{
+ VALUE str;
+
+ str = rb_str_new(0, 0);
+ lh_doall_arg(conf->data, LHASH_DOALL_ARG_FN(dump_conf_value), (void*)str);
+
+ return str;
+}
+
+static VALUE
+ossl_config_to_s(VALUE self)
+{
+ CONF *conf;
+
+ GetConfig(self, conf);
+
+ return dump_conf(conf);
+}
+
+static void
+each_conf_value(CONF_VALUE *cv, void* dummy)
+{
+ STACK_OF(CONF_VALUE) *sk;
+ CONF_VALUE *v;
+ VALUE section, name, value, args;
+ int i, num;
+
+ if (cv->name) return;
+ sk = (STACK_OF(CONF_VALUE)*)cv->value;
+ num = sk_CONF_VALUE_num(sk);
+ section = rb_str_new2(cv->section);
+ for(i = 0; i < num; i++){
+ v = sk_CONF_VALUE_value(sk, i);
+ name = v->name ? rb_str_new2(v->name) : Qnil;
+ value = v->value ? rb_str_new2(v->value) : Qnil;
+ args = rb_ary_new3(3, section, name, value);
+ rb_yield(args);
+ }
+}
+
+static IMPLEMENT_LHASH_DOALL_ARG_FN(each_conf_value, CONF_VALUE*, void*);
+
+static VALUE
+ossl_config_each(VALUE self)
+{
+ CONF *conf;
+
+ GetConfig(self, conf);
+ lh_doall_arg(conf->data, LHASH_DOALL_ARG_FN(each_conf_value), (void*)NULL);
+
+ return self;
+}
+#else
+static VALUE
+ossl_config_get_sections(VALUE self)
+{
+ rb_warn("#sections don't work with %s", OPENSSL_VERSION_TEXT);
+ return rb_ary_new();
+}
+
+static VALUE
+ossl_config_to_s(VALUE self)
+{
+ rb_warn("#to_s don't work with %s", OPENSSL_VERSION_TEXT);
+ return rb_str_new(0, 0);
+}
+
+static VALUE
+ossl_config_each(VALUE self)
+{
+ rb_warn("#each don't work with %s", OPENSSL_VERSION_TEXT);
+ return self;
+}
+#endif
+
+static VALUE
+ossl_config_inspect(VALUE self)
+{
+ VALUE str, ary = ossl_config_get_sections(self);
+ char *cname = rb_class2name(rb_obj_class(self));
+
+ str = rb_str_new2("#<");
+ rb_str_cat2(str, cname);
+ rb_str_cat2(str, " sections=");
+ rb_str_append(str, rb_inspect(ary));
+ rb_str_cat2(str, ">");
+
+ return str;
+}
+
+/*
+ * INIT
+ */
+void
+Init_ossl_config()
+{
+ eConfigError = rb_define_class_under(mOSSL, "ConfigError", eOSSLError);
+ cConfig = rb_define_class_under(mOSSL, "Config", rb_cObject);
+
+ rb_define_const(cConfig, "DEFAULT_CONFIG_FILE",
+ rb_str_new2(CONF_get1_default_config_file()));
+ rb_include_module(cConfig, rb_mEnumerable);
+ rb_define_singleton_method(cConfig, "parse", ossl_config_s_parse, 1);
+ rb_define_alias(CLASS_OF(cConfig), "load", "new");
+ rb_define_alloc_func(cConfig, ossl_config_s_alloc);
+ rb_define_copy_func(cConfig, ossl_config_copy);
+ rb_define_method(cConfig, "initialize", ossl_config_initialize, -1);
+ rb_define_method(cConfig, "get_value", ossl_config_get_value, 2);
+ rb_define_method(cConfig, "value", ossl_config_get_value_old, -1);
+ rb_define_method(cConfig, "add_value", ossl_config_add_value, 3);
+ rb_define_method(cConfig, "[]", ossl_config_get_section, 1);
+ rb_define_method(cConfig, "section", ossl_config_get_section_old, 1);
+ rb_define_method(cConfig, "[]=", ossl_config_set_section, 2);
+ rb_define_method(cConfig, "sections", ossl_config_get_sections, 0);
+ rb_define_method(cConfig, "to_s", ossl_config_to_s, 0);
+ rb_define_method(cConfig, "each", ossl_config_each, 0);
+ rb_define_method(cConfig, "inspect", ossl_config_inspect, 0);
+}
diff --git a/ruby_1_8_5/ext/openssl/ossl_config.h b/ruby_1_8_5/ext/openssl/ossl_config.h
new file mode 100644
index 0000000000..452d430b5e
--- /dev/null
+++ b/ruby_1_8_5/ext/openssl/ossl_config.h
@@ -0,0 +1,22 @@
+/*
+ * $Id: ossl_config.h,v 1.2 2003/09/08 10:31:38 gotoyuzo Exp $
+ * '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_CONFIG_H_)
+#define _OSSL_CONFIG_H_
+
+extern VALUE cConfig;
+extern VALUE eConfigError;
+
+CONF* GetConfigPtr(VALUE obj);
+CONF* DupConfigPtr(VALUE obj);
+void Init_ossl_config(void);
+
+#endif /* _OSSL_CONFIG_H_ */
+
diff --git a/ruby_1_8_5/ext/openssl/ossl_digest.c b/ruby_1_8_5/ext/openssl/ossl_digest.c
new file mode 100644
index 0000000000..8b9c273f4d
--- /dev/null
+++ b/ruby_1_8_5/ext/openssl/ossl_digest.c
@@ -0,0 +1,294 @@
+/*
+ * $Id: ossl_digest.c,v 1.4.2.2 2004/12/15 01:54:39 matz Exp $
+ * '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'.)
+ */
+#include "ossl.h"
+
+#define GetDigest(obj, ctx) do { \
+ Data_Get_Struct(obj, EVP_MD_CTX, ctx); \
+ if (!ctx) { \
+ ossl_raise(rb_eRuntimeError, "Digest CTX wasn't initialized!"); \
+ } \
+} while (0)
+#define SafeGetDigest(obj, ctx) do { \
+ OSSL_Check_Kind(obj, cDigest); \
+ GetDigest(obj, ctx); \
+} while (0)
+
+/*
+ * Classes
+ */
+VALUE mDigest;
+VALUE cDigest;
+VALUE eDigestError;
+
+static VALUE ossl_digest_alloc(VALUE klass);
+
+/*
+ * Public
+ */
+const EVP_MD *
+GetDigestPtr(VALUE obj)
+{
+ EVP_MD_CTX *ctx;
+
+ SafeGetDigest(obj, ctx);
+
+ return EVP_MD_CTX_md(ctx); /*== ctx->digest*/
+}
+
+VALUE
+ossl_digest_new(const EVP_MD *md)
+{
+ VALUE ret;
+ EVP_MD_CTX *ctx;
+
+ ret = ossl_digest_alloc(cDigest);
+ GetDigest(ret, ctx);
+ EVP_MD_CTX_init(ctx);
+ EVP_DigestInit_ex(ctx, md, NULL);
+
+ return ret;
+}
+
+/*
+ * Private
+ */
+static VALUE
+ossl_digest_alloc(VALUE klass)
+{
+ EVP_MD_CTX *ctx;
+ VALUE obj;
+
+ ctx = EVP_MD_CTX_create();
+ if (ctx == NULL)
+ ossl_raise(rb_eRuntimeError, "EVP_MD_CTX_create() failed");
+ EVP_MD_CTX_init(ctx);
+ obj = Data_Wrap_Struct(klass, 0, EVP_MD_CTX_destroy, ctx);
+
+ return obj;
+}
+
+VALUE ossl_digest_update(VALUE, VALUE);
+
+static VALUE
+ossl_digest_initialize(int argc, VALUE *argv, VALUE self)
+{
+ EVP_MD_CTX *ctx;
+ const EVP_MD *md;
+ char *name;
+ VALUE type, data;
+
+ rb_scan_args(argc, argv, "11", &type, &data);
+ StringValue(type);
+ if (!NIL_P(data)) StringValue(data);
+ name = StringValuePtr(type);
+
+ md = EVP_get_digestbyname(name);
+ if (!md) {
+ ossl_raise(rb_eRuntimeError, "Unsupported digest algorithm (%s).", name);
+ }
+ GetDigest(self, ctx);
+ EVP_DigestInit_ex(ctx, md, NULL);
+
+ if (!NIL_P(data)) return ossl_digest_update(self, data);
+ return self;
+}
+
+static VALUE
+ossl_digest_copy(VALUE self, VALUE other)
+{
+ EVP_MD_CTX *ctx1, *ctx2;
+
+ rb_check_frozen(self);
+ if (self == other) return self;
+
+ GetDigest(self, ctx1);
+ SafeGetDigest(other, ctx2);
+
+ if (!EVP_MD_CTX_copy(ctx1, ctx2)) {
+ ossl_raise(eDigestError, NULL);
+ }
+ return self;
+}
+
+static VALUE
+ossl_digest_reset(VALUE self)
+{
+ EVP_MD_CTX *ctx;
+
+ GetDigest(self, ctx);
+ EVP_DigestInit_ex(ctx, EVP_MD_CTX_md(ctx), NULL);
+
+ return self;
+}
+
+VALUE
+ossl_digest_update(VALUE self, VALUE data)
+{
+ EVP_MD_CTX *ctx;
+
+ StringValue(data);
+ GetDigest(self, ctx);
+ EVP_DigestUpdate(ctx, RSTRING(data)->ptr, RSTRING(data)->len);
+
+ return self;
+}
+
+static void
+digest_final(EVP_MD_CTX *ctx, char **buf, int *buf_len)
+{
+ EVP_MD_CTX final;
+
+ if (!EVP_MD_CTX_copy(&final, ctx)) {
+ ossl_raise(eDigestError, NULL);
+ }
+ if (!(*buf = OPENSSL_malloc(EVP_MD_CTX_size(&final)))) {
+ EVP_MD_CTX_cleanup(&final);
+ ossl_raise(eDigestError, "Cannot allocate mem for digest");
+ }
+ EVP_DigestFinal_ex(&final, *buf, buf_len);
+ EVP_MD_CTX_cleanup(&final);
+}
+
+static VALUE
+ossl_digest_digest(VALUE self)
+{
+ EVP_MD_CTX *ctx;
+ char *buf;
+ int buf_len;
+ VALUE digest;
+
+ GetDigest(self, ctx);
+ digest_final(ctx, &buf, &buf_len);
+ digest = ossl_buf2str(buf, buf_len);
+
+ return digest;
+}
+
+static VALUE
+ossl_digest_hexdigest(VALUE self)
+{
+ EVP_MD_CTX *ctx;
+ char *buf, *hexbuf;
+ int buf_len;
+ VALUE hexdigest;
+
+ GetDigest(self, ctx);
+ digest_final(ctx, &buf, &buf_len);
+ if (string2hex(buf, buf_len, &hexbuf, NULL) != 2 * buf_len) {
+ OPENSSL_free(buf);
+ ossl_raise(eDigestError, "Memory alloc error");
+ }
+ OPENSSL_free(buf);
+ hexdigest = ossl_buf2str(hexbuf, 2 * buf_len);
+
+ return hexdigest;
+}
+
+static VALUE
+ossl_digest_s_digest(VALUE klass, VALUE str, VALUE data)
+{
+ VALUE obj = rb_class_new_instance(1, &str, klass);
+
+ ossl_digest_update(obj, data);
+
+ return ossl_digest_digest(obj);
+}
+
+static VALUE
+ossl_digest_s_hexdigest(VALUE klass, VALUE str, VALUE data)
+{
+ VALUE obj = rb_class_new_instance(1, &str, klass);
+
+ ossl_digest_update(obj, data);
+
+ return ossl_digest_hexdigest(obj);
+}
+
+static VALUE
+ossl_digest_equal(VALUE self, VALUE other)
+{
+ EVP_MD_CTX *ctx;
+ VALUE str1, str2;
+
+ if (rb_obj_is_kind_of(other, cDigest) == Qtrue) {
+ str2 = ossl_digest_digest(other);
+ } else {
+ StringValue(other);
+ str2 = other;
+ }
+ GetDigest(self, ctx);
+ if (RSTRING(str2)->len == EVP_MD_CTX_size(ctx)) {
+ str1 = ossl_digest_digest(self);
+ } else {
+ str1 = ossl_digest_hexdigest(self);
+ }
+ if (RSTRING(str1)->len == RSTRING(str2)->len
+ && rb_str_cmp(str1, str2) == 0) {
+ return Qtrue;
+ }
+
+ return Qfalse;
+}
+
+static VALUE
+ossl_digest_name(VALUE self)
+{
+ EVP_MD_CTX *ctx;
+
+ GetDigest(self, ctx);
+
+ return rb_str_new2(EVP_MD_name(EVP_MD_CTX_md(ctx)));
+}
+
+static VALUE
+ossl_digest_size(VALUE self)
+{
+ EVP_MD_CTX *ctx;
+
+ GetDigest(self, ctx);
+
+ return INT2NUM(EVP_MD_CTX_size(ctx));
+}
+
+/*
+ * INIT
+ */
+void
+Init_ossl_digest()
+{
+ mDigest = rb_define_module_under(mOSSL, "Digest");
+
+ eDigestError = rb_define_class_under(mDigest, "DigestError", eOSSLError);
+
+ cDigest = rb_define_class_under(mDigest, "Digest", rb_cObject);
+
+ rb_define_alloc_func(cDigest, ossl_digest_alloc);
+ rb_define_singleton_method(cDigest, "digest", ossl_digest_s_digest, 2);
+ rb_define_singleton_method(cDigest, "hexdigest", ossl_digest_s_hexdigest, 2);
+
+ rb_define_method(cDigest, "initialize", ossl_digest_initialize, -1);
+ rb_define_method(cDigest, "reset", ossl_digest_reset, 0);
+
+ rb_define_copy_func(cDigest, ossl_digest_copy);
+
+ rb_define_method(cDigest, "digest", ossl_digest_digest, 0);
+ rb_define_method(cDigest, "hexdigest", ossl_digest_hexdigest, 0);
+ rb_define_alias(cDigest, "inspect", "hexdigest");
+ rb_define_alias(cDigest, "to_s", "hexdigest");
+
+ rb_define_method(cDigest, "update", ossl_digest_update, 1);
+ rb_define_alias(cDigest, "<<", "update");
+
+ rb_define_method(cDigest, "==", ossl_digest_equal, 1);
+
+ rb_define_method(cDigest, "name", ossl_digest_name, 0);
+ rb_define_method(cDigest, "size", ossl_digest_size, 0);
+}
diff --git a/ruby_1_8_5/ext/openssl/ossl_digest.h b/ruby_1_8_5/ext/openssl/ossl_digest.h
new file mode 100644
index 0000000000..b35bd217b3
--- /dev/null
+++ b/ruby_1_8_5/ext/openssl/ossl_digest.h
@@ -0,0 +1,23 @@
+/*
+ * $Id: ossl_digest.h,v 1.2 2003/09/05 09:08:40 gotoyuzo Exp $
+ * '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_DIGEST_H_)
+#define _OSSL_DIGEST_H_
+
+extern VALUE mDigest;
+extern VALUE cDigest;
+extern VALUE eDigestError;
+
+const EVP_MD *GetDigestPtr(VALUE);
+VALUE ossl_digest_new(const EVP_MD *);
+void Init_ossl_digest(void);
+
+#endif /* _OSSL_DIGEST_H_ */
+
diff --git a/ruby_1_8_5/ext/openssl/ossl_engine.c b/ruby_1_8_5/ext/openssl/ossl_engine.c
new file mode 100644
index 0000000000..6cc0183c0e
--- /dev/null
+++ b/ruby_1_8_5/ext/openssl/ossl_engine.c
@@ -0,0 +1,393 @@
+/*
+ * $Id: ossl_engine.c,v 1.4.2.6 2005/09/18 22:56:11 gotoyuzo Exp $
+ * 'OpenSSL for Ruby' project
+ * Copyright (C) 2003 GOTOU Yuuzou <gotoyuzo@notwork.org>
+ * All rights reserved.
+ */
+/*
+ * This program is licenced under the same licence as Ruby.
+ * (See the file 'LICENCE'.)
+ */
+#include "ossl.h"
+
+#if defined(OSSL_ENGINE_ENABLED)
+
+#define WrapEngine(klass, obj, engine) do { \
+ if (!engine) { \
+ ossl_raise(rb_eRuntimeError, "ENGINE wasn't initialized."); \
+ } \
+ obj = Data_Wrap_Struct(klass, 0, ENGINE_free, engine); \
+} while(0)
+#define GetEngine(obj, engine) do { \
+ Data_Get_Struct(obj, ENGINE, engine); \
+ if (!engine) { \
+ ossl_raise(rb_eRuntimeError, "ENGINE wasn't initialized."); \
+ } \
+} while (0)
+#define SafeGetEngine(obj, engine) do { \
+ OSSL_Check_Kind(obj, cEngine); \
+ GetPKCS7(obj, engine); \
+} while (0)
+
+/*
+ * Classes
+ */
+VALUE cEngine;
+VALUE eEngineError;
+
+/*
+ * Private
+ */
+#define OSSL_ENGINE_LOAD_IF_MATCH(x) \
+do{\
+ if(!strcmp(#x, RSTRING(name)->ptr)){\
+ ENGINE_load_##x();\
+ return Qtrue;\
+ }\
+}while(0)
+
+static VALUE
+ossl_engine_s_load(int argc, VALUE *argv, VALUE klass)
+{
+#if !defined(HAVE_ENGINE_LOAD_BUILTIN_ENGINES)
+ return Qnil;
+#else
+ VALUE name;
+
+ rb_scan_args(argc, argv, "01", &name);
+ if(NIL_P(name)){
+ ENGINE_load_builtin_engines();
+ return Qtrue;
+ }
+ StringValue(name);
+#ifndef OPENSSL_NO_STATIC_ENGINE
+ OSSL_ENGINE_LOAD_IF_MATCH(dynamic);
+ OSSL_ENGINE_LOAD_IF_MATCH(cswift);
+ OSSL_ENGINE_LOAD_IF_MATCH(chil);
+ OSSL_ENGINE_LOAD_IF_MATCH(atalla);
+ OSSL_ENGINE_LOAD_IF_MATCH(nuron);
+ OSSL_ENGINE_LOAD_IF_MATCH(ubsec);
+ OSSL_ENGINE_LOAD_IF_MATCH(aep);
+ OSSL_ENGINE_LOAD_IF_MATCH(sureware);
+ OSSL_ENGINE_LOAD_IF_MATCH(4758cca);
+#endif
+#ifdef HAVE_ENGINE_LOAD_OPENBSD_DEV_CRYPTO
+ OSSL_ENGINE_LOAD_IF_MATCH(openbsd_dev_crypto);
+#endif
+ OSSL_ENGINE_LOAD_IF_MATCH(openssl);
+ rb_warning("no such builtin loader for `%s'", RSTRING(name)->ptr);
+ return Qnil;
+#endif /* HAVE_ENGINE_LOAD_BUILTIN_ENGINES */
+}
+
+static VALUE
+ossl_engine_s_cleanup(VALUE self)
+{
+#if defined(HAVE_ENGINE_CLEANUP)
+ ENGINE_cleanup();
+#endif
+ return Qnil;
+}
+
+static VALUE
+ossl_engine_s_engines(VALUE klass)
+{
+ ENGINE *e;
+ VALUE ary, obj;
+
+ ary = rb_ary_new();
+ for(e = ENGINE_get_first(); e; e = ENGINE_get_next(e)){
+ WrapEngine(klass, obj, e);
+ rb_ary_push(ary, obj);
+ }
+
+ return ary;
+}
+
+static VALUE
+ossl_engine_s_by_id(VALUE klass, VALUE id)
+{
+ ENGINE *e;
+ VALUE obj;
+
+ StringValue(id);
+ ossl_engine_s_load(1, &id, klass);
+ if(!(e = ENGINE_by_id(RSTRING(id)->ptr)))
+ ossl_raise(eEngineError, NULL);
+ WrapEngine(klass, obj, e);
+ if(rb_block_given_p()) rb_yield(obj);
+ if(!ENGINE_init(e))
+ ossl_raise(eEngineError, NULL);
+ ENGINE_ctrl(e, ENGINE_CTRL_SET_PASSWORD_CALLBACK,
+ 0, NULL, (void(*)())ossl_pem_passwd_cb);
+ ERR_clear_error();
+
+ return obj;
+}
+
+static VALUE
+ossl_engine_s_alloc(VALUE klass)
+{
+ ENGINE *e;
+ VALUE obj;
+
+ if (!(e = ENGINE_new())) {
+ ossl_raise(eEngineError, NULL);
+ }
+ WrapEngine(klass, obj, e);
+
+ return obj;
+}
+
+static VALUE
+ossl_engine_get_id(VALUE self)
+{
+ ENGINE *e;
+ GetEngine(self, e);
+ return rb_str_new2(ENGINE_get_id(e));
+}
+
+static VALUE
+ossl_engine_get_name(VALUE self)
+{
+ ENGINE *e;
+ GetEngine(self, e);
+ return rb_str_new2(ENGINE_get_name(e));
+}
+
+static VALUE
+ossl_engine_finish(VALUE self)
+{
+ ENGINE *e;
+
+ GetEngine(self, e);
+ if(!ENGINE_finish(e)) ossl_raise(eEngineError, NULL);
+
+ return Qnil;
+}
+
+static VALUE
+ossl_engine_get_cipher(VALUE self, VALUE name)
+{
+#if defined(HAVE_ENGINE_GET_CIPHER)
+ ENGINE *e;
+ const EVP_CIPHER *ciph, *tmp;
+ char *s;
+ int nid;
+
+ s = StringValuePtr(name);
+ tmp = EVP_get_cipherbyname(s);
+ if(!tmp) ossl_raise(eEngineError, "no such cipher `%s'", s);
+ nid = EVP_CIPHER_nid(tmp);
+ GetEngine(self, e);
+ ciph = ENGINE_get_cipher(e, nid);
+ if(!ciph) ossl_raise(eEngineError, NULL);
+
+ return ossl_cipher_new(ciph);
+#else
+ rb_notimplement();
+#endif
+}
+
+static VALUE
+ossl_engine_get_digest(VALUE self, VALUE name)
+{
+#if defined(HAVE_ENGINE_GET_DIGEST)
+ ENGINE *e;
+ const EVP_MD *md, *tmp;
+ char *s;
+ int nid;
+
+ s = StringValuePtr(name);
+ tmp = EVP_get_digestbyname(s);
+ if(!tmp) ossl_raise(eEngineError, "no such digest `%s'", s);
+ nid = EVP_MD_nid(tmp);
+ GetEngine(self, e);
+ md = ENGINE_get_digest(e, nid);
+ if(!md) ossl_raise(eEngineError, NULL);
+
+ return ossl_digest_new(md);
+#else
+ rb_notimplement();
+#endif
+}
+
+static VALUE
+ossl_engine_load_privkey(int argc, VALUE *argv, VALUE self)
+{
+ ENGINE *e;
+ EVP_PKEY *pkey;
+ VALUE id, data, obj;
+ char *sid, *sdata;
+
+ rb_scan_args(argc, argv, "02", &id, &data);
+ sid = NIL_P(id) ? NULL : StringValuePtr(id);
+ sdata = NIL_P(data) ? NULL : StringValuePtr(data);
+ GetEngine(self, e);
+#if OPENSSL_VERSION_NUMBER < 0x00907000L
+ pkey = ENGINE_load_private_key(e, sid, sdata);
+#else
+ pkey = ENGINE_load_private_key(e, sid, NULL, sdata);
+#endif
+ if (!pkey) ossl_raise(eEngineError, NULL);
+ obj = ossl_pkey_new(pkey);
+ OSSL_PKEY_SET_PRIVATE(obj);
+
+ return obj;
+}
+
+static VALUE
+ossl_engine_load_pubkey(int argc, VALUE *argv, VALUE self)
+{
+ ENGINE *e;
+ EVP_PKEY *pkey;
+ VALUE id, data;
+ char *sid, *sdata;
+
+ rb_scan_args(argc, argv, "02", &id, &data);
+ sid = NIL_P(id) ? NULL : StringValuePtr(id);
+ sdata = NIL_P(data) ? NULL : StringValuePtr(data);
+ GetEngine(self, e);
+#if OPENSSL_VERSION_NUMBER < 0x00907000L
+ pkey = ENGINE_load_public_key(e, sid, sdata);
+#else
+ pkey = ENGINE_load_public_key(e, sid, NULL, sdata);
+#endif
+ if (!pkey) ossl_raise(eEngineError, NULL);
+
+ return ossl_pkey_new(pkey);
+}
+
+static VALUE
+ossl_engine_set_default(VALUE self, VALUE flag)
+{
+ ENGINE *e;
+ int f = NUM2INT(flag);
+
+ GetEngine(self, e);
+ ENGINE_set_default(e, f);
+
+ return Qtrue;
+}
+
+static VALUE
+ossl_engine_ctrl_cmd(int argc, VALUE *argv, VALUE self)
+{
+ ENGINE *e;
+ VALUE cmd, val;
+ int ret;
+
+ GetEngine(self, e);
+ rb_scan_args(argc, argv, "11", &cmd, &val);
+ StringValue(cmd);
+ if (!NIL_P(val)) StringValue(val);
+ ret = ENGINE_ctrl_cmd_string(e, RSTRING(cmd)->ptr,
+ NIL_P(val) ? NULL : RSTRING(val)->ptr, 0);
+ if (!ret) ossl_raise(eEngineError, NULL);
+
+ return self;
+}
+
+static VALUE
+ossl_engine_cmd_flag_to_name(int flag)
+{
+ switch(flag){
+ case ENGINE_CMD_FLAG_NUMERIC: return rb_str_new2("NUMERIC");
+ case ENGINE_CMD_FLAG_STRING: return rb_str_new2("STRING");
+ case ENGINE_CMD_FLAG_NO_INPUT: return rb_str_new2("NO_INPUT");
+ case ENGINE_CMD_FLAG_INTERNAL: return rb_str_new2("INTERNAL");
+ default: return rb_str_new2("UNKNOWN");
+ }
+}
+
+static VALUE
+ossl_engine_get_cmds(VALUE self)
+{
+ ENGINE *e;
+ const ENGINE_CMD_DEFN *defn, *p;
+ VALUE ary, tmp;
+
+ GetEngine(self, e);
+ ary = rb_ary_new();
+ if ((defn = ENGINE_get_cmd_defns(e)) != NULL){
+ for (p = defn; p->cmd_num > 0; p++){
+ tmp = rb_ary_new();
+ rb_ary_push(tmp, rb_str_new2(p->cmd_name));
+ rb_ary_push(tmp, rb_str_new2(p->cmd_desc));
+ rb_ary_push(tmp, ossl_engine_cmd_flag_to_name(p->cmd_flags));
+ rb_ary_push(ary, tmp);
+ }
+ }
+
+ return ary;
+}
+
+static VALUE
+ossl_engine_inspect(VALUE self)
+{
+ VALUE str;
+ char *cname = rb_class2name(rb_obj_class(self));
+
+ str = rb_str_new2("#<");
+ rb_str_cat2(str, cname);
+ rb_str_cat2(str, " id=\"");
+ rb_str_append(str, ossl_engine_get_id(self));
+ rb_str_cat2(str, "\" name=\"");
+ rb_str_append(str, ossl_engine_get_name(self));
+ rb_str_cat2(str, "\">");
+
+ return str;
+}
+
+#define DefEngineConst(x) rb_define_const(cEngine, #x, INT2NUM(ENGINE_##x))
+
+void
+Init_ossl_engine()
+{
+ cEngine = rb_define_class_under(mOSSL, "Engine", rb_cObject);
+ eEngineError = rb_define_class_under(cEngine, "EngineError", eOSSLError);
+
+ rb_define_alloc_func(cEngine, ossl_engine_s_alloc);
+ rb_define_singleton_method(cEngine, "load", ossl_engine_s_load, -1);
+ rb_define_singleton_method(cEngine, "cleanup", ossl_engine_s_cleanup, 0);
+ rb_define_singleton_method(cEngine, "engines", ossl_engine_s_engines, 0);
+ rb_define_singleton_method(cEngine, "by_id", ossl_engine_s_by_id, 1);
+ rb_undef_method(CLASS_OF(cEngine), "new");
+
+ rb_define_method(cEngine, "id", ossl_engine_get_id, 0);
+ rb_define_method(cEngine, "name", ossl_engine_get_name, 0);
+ rb_define_method(cEngine, "finish", ossl_engine_finish, 0);
+ rb_define_method(cEngine, "cipher", ossl_engine_get_cipher, 1);
+ rb_define_method(cEngine, "digest", ossl_engine_get_digest, 1);
+ rb_define_method(cEngine, "load_private_key", ossl_engine_load_privkey, -1);
+ rb_define_method(cEngine, "load_public_key", ossl_engine_load_pubkey, -1);
+ rb_define_method(cEngine, "set_default", ossl_engine_set_default, 1);
+ rb_define_method(cEngine, "ctrl_cmd", ossl_engine_ctrl_cmd, -1);
+ rb_define_method(cEngine, "cmds", ossl_engine_get_cmds, 0);
+ rb_define_method(cEngine, "inspect", ossl_engine_inspect, 0);
+
+ DefEngineConst(METHOD_RSA);
+ DefEngineConst(METHOD_DSA);
+ DefEngineConst(METHOD_DH);
+ DefEngineConst(METHOD_RAND);
+#ifdef ENGINE_METHOD_BN_MOD_EXP
+ DefEngineConst(METHOD_BN_MOD_EXP);
+#endif
+#ifdef ENGINE_METHOD_BN_MOD_EXP_CRT
+ DefEngineConst(METHOD_BN_MOD_EXP_CRT);
+#endif
+#ifdef ENGINE_METHOD_CIPHERS
+ DefEngineConst(METHOD_CIPHERS);
+#endif
+#ifdef ENGINE_METHOD_DIGESTS
+ DefEngineConst(METHOD_DIGESTS);
+#endif
+ DefEngineConst(METHOD_ALL);
+ DefEngineConst(METHOD_NONE);
+}
+#else
+void
+Init_ossl_engine()
+{
+}
+#endif
diff --git a/ruby_1_8_5/ext/openssl/ossl_engine.h b/ruby_1_8_5/ext/openssl/ossl_engine.h
new file mode 100644
index 0000000000..ccc426481a
--- /dev/null
+++ b/ruby_1_8_5/ext/openssl/ossl_engine.h
@@ -0,0 +1,20 @@
+/*
+ * $Id: ossl_engine.h,v 1.1 2003/10/02 08:47:11 gotoyuzo Exp $
+ * 'OpenSSL for Ruby' project
+ * Copyright (C) 2003 Michal Rokos <m.rokos@sh.cvut.cz>
+ * Copyright (C) 2003 GOTOU Yuuzou <gotoyuzo@notwork.org>
+ * All rights reserved.
+ */
+/*
+ * This program is licenced under the same licence as Ruby.
+ * (See the file 'LICENCE'.)
+ */
+#if !defined(OSSL_ENGINE_H)
+#define OSSL_ENGINE_H
+
+extern VALUE cEngine;
+extern VALUE eEngineError;
+
+void Init_ossl_engine(void);
+
+#endif /* OSSL_ENGINE_H */
diff --git a/ruby_1_8_5/ext/openssl/ossl_hmac.c b/ruby_1_8_5/ext/openssl/ossl_hmac.c
new file mode 100644
index 0000000000..cd66ab6e2c
--- /dev/null
+++ b/ruby_1_8_5/ext/openssl/ossl_hmac.c
@@ -0,0 +1,220 @@
+/*
+ * $Id: ossl_hmac.c,v 1.4.2.2 2004/12/15 01:54:39 matz Exp $
+ * '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(OPENSSL_NO_HMAC)
+
+#include "ossl.h"
+
+#define MakeHMAC(obj, klass, ctx) \
+ obj = Data_Make_Struct(klass, HMAC_CTX, 0, ossl_hmac_free, ctx)
+#define GetHMAC(obj, ctx) do { \
+ Data_Get_Struct(obj, HMAC_CTX, ctx); \
+ if (!ctx) { \
+ ossl_raise(rb_eRuntimeError, "HMAC wasn't initialized"); \
+ } \
+} while (0)
+#define SafeGetHMAC(obj, ctx) do { \
+ OSSL_Check_Kind(obj, cHMAC); \
+ GetHMAC(obj, ctx); \
+} while (0)
+
+/*
+ * Classes
+ */
+VALUE cHMAC;
+VALUE eHMACError;
+
+/*
+ * Public
+ */
+
+/*
+ * Private
+ */
+static void
+ossl_hmac_free(HMAC_CTX *ctx)
+{
+ HMAC_CTX_cleanup(ctx);
+ free(ctx);
+}
+
+static VALUE
+ossl_hmac_alloc(VALUE klass)
+{
+ HMAC_CTX *ctx;
+ VALUE obj;
+
+ MakeHMAC(obj, klass, ctx);
+ HMAC_CTX_init(ctx);
+
+ return obj;
+}
+
+static VALUE
+ossl_hmac_initialize(VALUE self, VALUE key, VALUE digest)
+{
+ HMAC_CTX *ctx;
+
+ StringValue(key);
+ GetHMAC(self, ctx);
+ HMAC_Init_ex(ctx, RSTRING(key)->ptr, RSTRING(key)->len,
+ GetDigestPtr(digest), NULL);
+
+ return self;
+}
+
+static VALUE
+ossl_hmac_copy(VALUE self, VALUE other)
+{
+ HMAC_CTX *ctx1, *ctx2;
+
+ rb_check_frozen(self);
+ if (self == other) return self;
+
+ GetHMAC(self, ctx1);
+ SafeGetHMAC(other, ctx2);
+
+ if (!HMAC_CTX_copy(ctx1, ctx2)) {
+ ossl_raise(eHMACError, NULL);
+ }
+ return self;
+}
+
+static VALUE
+ossl_hmac_update(VALUE self, VALUE data)
+{
+ HMAC_CTX *ctx;
+
+ StringValue(data);
+ GetHMAC(self, ctx);
+ HMAC_Update(ctx, RSTRING(data)->ptr, RSTRING(data)->len);
+
+ return self;
+}
+
+static void
+hmac_final(HMAC_CTX *ctx, char **buf, int *buf_len)
+{
+ HMAC_CTX final;
+
+ if (!HMAC_CTX_copy(&final, ctx)) {
+ ossl_raise(eHMACError, NULL);
+ }
+ if (!(*buf = OPENSSL_malloc(HMAC_size(&final)))) {
+ HMAC_CTX_cleanup(&final);
+ OSSL_Debug("Allocating %d mem", HMAC_size(&final));
+ ossl_raise(eHMACError, "Cannot allocate memory for hmac");
+ }
+ HMAC_Final(&final, *buf, buf_len);
+ HMAC_CTX_cleanup(&final);
+}
+
+static VALUE
+ossl_hmac_digest(VALUE self)
+{
+ HMAC_CTX *ctx;
+ char *buf;
+ int buf_len;
+ VALUE digest;
+
+ GetHMAC(self, ctx);
+ hmac_final(ctx, &buf, &buf_len);
+ digest = ossl_buf2str(buf, buf_len);
+
+ return digest;
+}
+
+static VALUE
+ossl_hmac_hexdigest(VALUE self)
+{
+ HMAC_CTX *ctx;
+ char *buf, *hexbuf;
+ int buf_len;
+ VALUE hexdigest;
+
+ GetHMAC(self, ctx);
+ hmac_final(ctx, &buf, &buf_len);
+ if (string2hex(buf, buf_len, &hexbuf, NULL) != 2 * buf_len) {
+ OPENSSL_free(buf);
+ ossl_raise(eHMACError, "Memory alloc error");
+ }
+ OPENSSL_free(buf);
+ hexdigest = ossl_buf2str(hexbuf, 2 * buf_len);
+
+ return hexdigest;
+}
+
+static VALUE
+ossl_hmac_s_digest(VALUE klass, VALUE digest, VALUE key, VALUE data)
+{
+ char *buf;
+ int buf_len;
+
+ StringValue(key);
+ StringValue(data);
+ buf = HMAC(GetDigestPtr(digest), RSTRING(key)->ptr, RSTRING(key)->len,
+ RSTRING(data)->ptr, RSTRING(data)->len, NULL, &buf_len);
+
+ return rb_str_new(buf, buf_len);
+}
+
+static VALUE
+ossl_hmac_s_hexdigest(VALUE klass, VALUE digest, VALUE key, VALUE data)
+{
+ char *buf, *hexbuf;
+ int buf_len;
+ VALUE hexdigest;
+
+ StringValue(key);
+ StringValue(data);
+
+ buf = HMAC(GetDigestPtr(digest), RSTRING(key)->ptr, RSTRING(key)->len,
+ RSTRING(data)->ptr, RSTRING(data)->len, NULL, &buf_len);
+ if (string2hex(buf, buf_len, &hexbuf, NULL) != 2 * buf_len) {
+ ossl_raise(eHMACError, "Cannot convert buf to hexbuf");
+ }
+ hexdigest = ossl_buf2str(hexbuf, 2 * buf_len);
+
+ return hexdigest;
+}
+
+/*
+ * INIT
+ */
+void
+Init_ossl_hmac()
+{
+ eHMACError = rb_define_class_under(mOSSL, "HMACError", eOSSLError);
+
+ cHMAC = rb_define_class_under(mOSSL, "HMAC", rb_cObject);
+
+ rb_define_alloc_func(cHMAC, ossl_hmac_alloc);
+ rb_define_singleton_method(cHMAC, "digest", ossl_hmac_s_digest, 3);
+ rb_define_singleton_method(cHMAC, "hexdigest", ossl_hmac_s_hexdigest, 3);
+
+ rb_define_method(cHMAC, "initialize", ossl_hmac_initialize, 2);
+ rb_define_copy_func(cHMAC, ossl_hmac_copy);
+
+ rb_define_method(cHMAC, "update", ossl_hmac_update, 1);
+ rb_define_alias(cHMAC, "<<", "update");
+ rb_define_method(cHMAC, "digest", ossl_hmac_digest, 0);
+ rb_define_method(cHMAC, "hexdigest", ossl_hmac_hexdigest, 0);
+ rb_define_alias(cHMAC, "inspect", "hexdigest");
+ rb_define_alias(cHMAC, "to_s", "hexdigest");
+}
+
+#else /* NO_HMAC */
+# warning >>> OpenSSL is compiled without HMAC support <<<
+void
+Init_ossl_hmac()
+{
+ rb_warning("HMAC will NOT be avaible: OpenSSL is compiled without HMAC.");
+}
+#endif /* NO_HMAC */
diff --git a/ruby_1_8_5/ext/openssl/ossl_hmac.h b/ruby_1_8_5/ext/openssl/ossl_hmac.h
new file mode 100644
index 0000000000..2c8d69c177
--- /dev/null
+++ b/ruby_1_8_5/ext/openssl/ossl_hmac.h
@@ -0,0 +1,19 @@
+/*
+ * $Id: ossl_hmac.h,v 1.1 2003/07/23 16:11:29 gotoyuzo Exp $
+ * '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_HMAC_H_)
+#define _OSSL_HMAC_H_
+
+extern VALUE cHMAC;
+extern VALUE eHMACError;
+
+void Init_ossl_hmac(void);
+
+#endif /* _OSSL_HMAC_H_ */
diff --git a/ruby_1_8_5/ext/openssl/ossl_ns_spki.c b/ruby_1_8_5/ext/openssl/ossl_ns_spki.c
new file mode 100644
index 0000000000..bd8c59faf9
--- /dev/null
+++ b/ruby_1_8_5/ext/openssl/ossl_ns_spki.c
@@ -0,0 +1,256 @@
+/*
+ * $Id: ossl_ns_spki.c,v 1.3.2.5 2006/03/17 10:10:53 gotoyuzo Exp $
+ * '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'.)
+ */
+#include "ossl.h"
+
+#define WrapSPKI(klass, obj, spki) do { \
+ if (!spki) { \
+ ossl_raise(rb_eRuntimeError, "SPKI wasn't initialized!"); \
+ } \
+ obj = Data_Wrap_Struct(klass, 0, NETSCAPE_SPKI_free, spki); \
+} while (0)
+#define GetSPKI(obj, spki) do { \
+ Data_Get_Struct(obj, NETSCAPE_SPKI, spki); \
+ if (!spki) { \
+ ossl_raise(rb_eRuntimeError, "SPKI wasn't initialized!"); \
+ } \
+} while (0)
+
+/*
+ * Classes
+ */
+VALUE mNetscape;
+VALUE cSPKI;
+VALUE eSPKIError;
+
+/*
+ * Public functions
+ */
+
+/*
+ * Private functions
+ */
+static VALUE
+ossl_spki_alloc(VALUE klass)
+{
+ NETSCAPE_SPKI *spki;
+ VALUE obj;
+
+ if (!(spki = NETSCAPE_SPKI_new())) {
+ ossl_raise(eSPKIError, NULL);
+ }
+ WrapSPKI(klass, obj, spki);
+
+ return obj;
+}
+
+static VALUE
+ossl_spki_initialize(int argc, VALUE *argv, VALUE self)
+{
+ NETSCAPE_SPKI *spki;
+ VALUE buffer;
+ unsigned char *p;
+
+ if (rb_scan_args(argc, argv, "01", &buffer) == 0) {
+ return self;
+ }
+ StringValue(buffer);
+ if (!(spki = NETSCAPE_SPKI_b64_decode(RSTRING(buffer)->ptr, -1))) {
+ p = RSTRING(buffer)->ptr;
+ if (!(spki = d2i_NETSCAPE_SPKI(NULL, &p, RSTRING(buffer)->len))) {
+ ossl_raise(eSPKIError, NULL);
+ }
+ }
+ NETSCAPE_SPKI_free(DATA_PTR(self));
+ DATA_PTR(self) = spki;
+
+ return self;
+}
+
+static VALUE
+ossl_spki_to_der(VALUE self)
+{
+ NETSCAPE_SPKI *spki;
+ VALUE str;
+ long len;
+ unsigned char *p;
+
+ GetSPKI(self, spki);
+ if ((len = i2d_NETSCAPE_SPKI(spki, NULL)) <= 0)
+ ossl_raise(eX509CertError, NULL);
+ str = rb_str_new(0, len);
+ p = RSTRING(str)->ptr;
+ if (i2d_NETSCAPE_SPKI(spki, &p) <= 0)
+ ossl_raise(eX509CertError, NULL);
+ ossl_str_adjust(str, p);
+
+ return str;
+}
+
+static VALUE
+ossl_spki_to_pem(VALUE self)
+{
+ NETSCAPE_SPKI *spki;
+ char *data;
+ VALUE str;
+
+ GetSPKI(self, spki);
+ if (!(data = NETSCAPE_SPKI_b64_encode(spki))) {
+ ossl_raise(eSPKIError, NULL);
+ }
+ str = ossl_buf2str(data, strlen(data));
+
+ return str;
+}
+
+static VALUE
+ossl_spki_print(VALUE self)
+{
+ NETSCAPE_SPKI *spki;
+ BIO *out;
+ BUF_MEM *buf;
+ VALUE str;
+
+ GetSPKI(self, spki);
+ if (!(out = BIO_new(BIO_s_mem()))) {
+ ossl_raise(eSPKIError, NULL);
+ }
+ if (!NETSCAPE_SPKI_print(out, spki)) {
+ BIO_free(out);
+ ossl_raise(eSPKIError, NULL);
+ }
+ BIO_get_mem_ptr(out, &buf);
+ str = rb_str_new(buf->data, buf->length);
+ BIO_free(out);
+
+ return str;
+}
+
+static VALUE
+ossl_spki_get_public_key(VALUE self)
+{
+ NETSCAPE_SPKI *spki;
+ EVP_PKEY *pkey;
+
+ GetSPKI(self, spki);
+ if (!(pkey = NETSCAPE_SPKI_get_pubkey(spki))) { /* adds an reference */
+ ossl_raise(eSPKIError, NULL);
+ }
+
+ return ossl_pkey_new(pkey); /* NO DUP - OK */
+}
+
+static VALUE
+ossl_spki_set_public_key(VALUE self, VALUE key)
+{
+ NETSCAPE_SPKI *spki;
+
+ GetSPKI(self, spki);
+ if (!NETSCAPE_SPKI_set_pubkey(spki, GetPKeyPtr(key))) { /* NO NEED TO DUP */
+ ossl_raise(eSPKIError, NULL);
+ }
+
+ return key;
+}
+
+static VALUE
+ossl_spki_get_challenge(VALUE self)
+{
+ NETSCAPE_SPKI *spki;
+
+ GetSPKI(self, spki);
+ if (spki->spkac->challenge->length <= 0) {
+ OSSL_Debug("Challenge.length <= 0?");
+ return rb_str_new(0, 0);
+ }
+
+ return rb_str_new(spki->spkac->challenge->data,
+ spki->spkac->challenge->length);
+}
+
+static VALUE
+ossl_spki_set_challenge(VALUE self, VALUE str)
+{
+ NETSCAPE_SPKI *spki;
+
+ StringValue(str);
+ GetSPKI(self, spki);
+ if (!ASN1_STRING_set(spki->spkac->challenge, RSTRING(str)->ptr,
+ RSTRING(str)->len)) {
+ ossl_raise(eSPKIError, NULL);
+ }
+
+ return str;
+}
+
+static VALUE
+ossl_spki_sign(VALUE self, VALUE key, VALUE digest)
+{
+ NETSCAPE_SPKI *spki;
+ EVP_PKEY *pkey;
+ const EVP_MD *md;
+
+ pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */
+ md = GetDigestPtr(digest);
+ GetSPKI(self, spki);
+ if (!NETSCAPE_SPKI_sign(spki, pkey, md)) {
+ ossl_raise(eSPKIError, NULL);
+ }
+
+ return self;
+}
+
+/*
+ * Checks that cert signature is made with PRIVversion of this PUBLIC 'key'
+ */
+static VALUE
+ossl_spki_verify(VALUE self, VALUE key)
+{
+ NETSCAPE_SPKI *spki;
+
+ GetSPKI(self, spki);
+ switch (NETSCAPE_SPKI_verify(spki, GetPKeyPtr(key))) { /* NO NEED TO DUP */
+ case 0:
+ return Qfalse;
+ case 1:
+ return Qtrue;
+ default:
+ ossl_raise(eSPKIError, NULL);
+ }
+ return Qnil; /* dummy */
+}
+
+/*
+ * NETSCAPE_SPKI init
+ */
+void
+Init_ossl_ns_spki()
+{
+ mNetscape = rb_define_module_under(mOSSL, "Netscape");
+
+ eSPKIError = rb_define_class_under(mNetscape, "SPKIError", eOSSLError);
+
+ cSPKI = rb_define_class_under(mNetscape, "SPKI", rb_cObject);
+
+ rb_define_alloc_func(cSPKI, ossl_spki_alloc);
+ rb_define_method(cSPKI, "initialize", ossl_spki_initialize, -1);
+
+ rb_define_method(cSPKI, "to_der", ossl_spki_to_der, 0);
+ rb_define_method(cSPKI, "to_pem", ossl_spki_to_pem, 0);
+ rb_define_alias(cSPKI, "to_s", "to_pem");
+ rb_define_method(cSPKI, "to_text", ossl_spki_print, 0);
+ rb_define_method(cSPKI, "public_key", ossl_spki_get_public_key, 0);
+ rb_define_method(cSPKI, "public_key=", ossl_spki_set_public_key, 1);
+ rb_define_method(cSPKI, "sign", ossl_spki_sign, 2);
+ rb_define_method(cSPKI, "verify", ossl_spki_verify, 1);
+ rb_define_method(cSPKI, "challenge", ossl_spki_get_challenge, 0);
+ rb_define_method(cSPKI, "challenge=", ossl_spki_set_challenge, 1);
+}
+
diff --git a/ruby_1_8_5/ext/openssl/ossl_ns_spki.h b/ruby_1_8_5/ext/openssl/ossl_ns_spki.h
new file mode 100644
index 0000000000..2ca1fdcd62
--- /dev/null
+++ b/ruby_1_8_5/ext/openssl/ossl_ns_spki.h
@@ -0,0 +1,21 @@
+/*
+ * $Id: ossl_ns_spki.h,v 1.1 2003/07/23 16:11:29 gotoyuzo Exp $
+ * '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_NS_SPKI_H_)
+#define _OSSL_NS_SPKI_H_
+
+extern VALUE mNetscape;
+extern VALUE cSPKI;
+extern VALUE eSPKIError;
+
+void Init_ossl_ns_spki(void);
+
+#endif /* _OSSL_NS_SPKI_H_ */
+
diff --git a/ruby_1_8_5/ext/openssl/ossl_ocsp.c b/ruby_1_8_5/ext/openssl/ossl_ocsp.c
new file mode 100644
index 0000000000..f2097b967e
--- /dev/null
+++ b/ruby_1_8_5/ext/openssl/ossl_ocsp.c
@@ -0,0 +1,769 @@
+/*
+ * $Id: ossl_ocsp.c,v 1.4.2.2 2005/01/22 20:28:02 gotoyuzo Exp $
+ * 'OpenSSL for Ruby' project
+ * Copyright (C) 2003 Michal Rokos <m.rokos@sh.cvut.cz>
+ * Copyright (C) 2003 GOTOU Yuuzou <gotoyuzo@notwork.org>
+ * All rights reserved.
+ */
+/*
+ * This program is licenced under the same licence as Ruby.
+ * (See the file 'LICENCE'.)
+ */
+#include "ossl.h"
+
+#if defined(OSSL_OCSP_ENABLED)
+
+#define WrapOCSPReq(klass, obj, req) do { \
+ if(!req) ossl_raise(rb_eRuntimeError, "Request wasn't initialized!"); \
+ obj = Data_Wrap_Struct(klass, 0, OCSP_REQUEST_free, req); \
+} while (0)
+#define GetOCSPReq(obj, req) do { \
+ Data_Get_Struct(obj, OCSP_REQUEST, req); \
+ if(!req) ossl_raise(rb_eRuntimeError, "Request wasn't initialized!"); \
+} while (0)
+#define SafeGetOCSPReq(obj, req) do { \
+ OSSL_Check_Kind(obj, cOCSPReq); \
+ GetOCSPReq(obj, req); \
+} while (0)
+
+#define WrapOCSPRes(klass, obj, res) do { \
+ if(!res) ossl_raise(rb_eRuntimeError, "Response wasn't initialized!"); \
+ obj = Data_Wrap_Struct(klass, 0, OCSP_RESPONSE_free, res); \
+} while (0)
+#define GetOCSPRes(obj, res) do { \
+ Data_Get_Struct(obj, OCSP_RESPONSE, res); \
+ if(!res) ossl_raise(rb_eRuntimeError, "Response wasn't initialized!"); \
+} while (0)
+#define SafeGetOCSPRes(obj, res) do { \
+ OSSL_Check_Kind(obj, cOCSPRes); \
+ GetOCSPRes(obj, res); \
+} while (0)
+
+#define WrapOCSPBasicRes(klass, obj, res) do { \
+ if(!res) ossl_raise(rb_eRuntimeError, "Response wasn't initialized!"); \
+ obj = Data_Wrap_Struct(klass, 0, OCSP_BASICRESP_free, res); \
+} while (0)
+#define GetOCSPBasicRes(obj, res) do { \
+ Data_Get_Struct(obj, OCSP_BASICRESP, res); \
+ if(!res) ossl_raise(rb_eRuntimeError, "Response wasn't initialized!"); \
+} while (0)
+#define SafeGetOCSPBasicRes(obj, res) do { \
+ OSSL_Check_Kind(obj, cOCSPBasicRes); \
+ GetOCSPBasicRes(obj, res); \
+} while (0)
+
+#define WrapOCSPCertId(klass, obj, cid) do { \
+ if(!cid) ossl_raise(rb_eRuntimeError, "Cert ID wasn't initialized!"); \
+ obj = Data_Wrap_Struct(klass, 0, OCSP_CERTID_free, cid); \
+} while (0)
+#define GetOCSPCertId(obj, cid) do { \
+ Data_Get_Struct(obj, OCSP_CERTID, cid); \
+ if(!cid) ossl_raise(rb_eRuntimeError, "Cert ID wasn't initialized!"); \
+} while (0)
+#define SafeGetOCSPCertId(obj, cid) do { \
+ OSSL_Check_Kind(obj, cOCSPCertId); \
+ GetOCSPCertId(obj, cid); \
+} while (0)
+
+VALUE mOCSP;
+VALUE eOCSPError;
+VALUE cOCSPReq;
+VALUE cOCSPRes;
+VALUE cOCSPBasicRes;
+VALUE cOCSPCertId;
+
+/*
+ * Public
+ */
+static VALUE
+ossl_ocspcertid_new(OCSP_CERTID *cid)
+{
+ VALUE obj;
+ WrapOCSPCertId(cOCSPCertId, obj, cid);
+ return obj;
+}
+
+/*
+ * OCSP::Resquest
+ */
+static VALUE
+ossl_ocspreq_alloc(VALUE klass)
+{
+ OCSP_REQUEST *req;
+ VALUE obj;
+
+ if (!(req = OCSP_REQUEST_new()))
+ ossl_raise(eOCSPError, NULL);
+ WrapOCSPReq(klass, obj, req);
+
+ return obj;
+}
+
+static VALUE
+ossl_ocspreq_initialize(int argc, VALUE *argv, VALUE self)
+{
+ VALUE arg;
+ unsigned char *p;
+
+ rb_scan_args(argc, argv, "01", &arg);
+ if(!NIL_P(arg)){
+ arg = ossl_to_der_if_possible(arg);
+ StringValue(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");
+ }
+ }
+
+ return self;
+}
+
+static VALUE
+ossl_ocspreq_add_nonce(int argc, VALUE *argv, VALUE self)
+{
+ OCSP_REQUEST *req;
+ VALUE val;
+ int ret;
+
+ rb_scan_args(argc, argv, "01", &val);
+ if(NIL_P(val)) {
+ GetOCSPReq(self, req);
+ ret = OCSP_request_add1_nonce(req, NULL, -1);
+ }
+ else{
+ StringValue(val);
+ GetOCSPReq(self, req);
+ ret = OCSP_request_add1_nonce(req, RSTRING(val)->ptr, RSTRING(val)->len);
+ }
+ if(!ret) ossl_raise(eOCSPError, NULL);
+
+ return self;
+}
+
+/* Check nonce validity in a request and response.
+ * Return value reflects result:
+ * 1: nonces present and equal.
+ * 2: nonces both absent.
+ * 3: nonce present in response only.
+ * 0: nonces both present and not equal.
+ * -1: nonce in request only.
+ *
+ * For most responders clients can check return > 0.
+ * If responder doesn't handle nonces return != 0 may be
+ * necessary. return == 0 is always an error.
+ */
+static VALUE
+ossl_ocspreq_check_nonce(VALUE self, VALUE basic_resp)
+{
+ OCSP_REQUEST *req;
+ OCSP_BASICRESP *bs;
+ int res;
+
+ GetOCSPReq(self, req);
+ SafeGetOCSPBasicRes(basic_resp, bs);
+ res = OCSP_check_nonce(req, bs);
+
+ return INT2NUM(res);
+}
+
+static VALUE
+ossl_ocspreq_add_certid(VALUE self, VALUE certid)
+{
+ OCSP_REQUEST *req;
+ OCSP_CERTID *id;
+
+ GetOCSPReq(self, req);
+ GetOCSPCertId(certid, id);
+ if(!OCSP_request_add0_id(req, OCSP_CERTID_dup(id)))
+ ossl_raise(eOCSPError, NULL);
+
+ return self;
+}
+
+static VALUE
+ossl_ocspreq_get_certid(VALUE self)
+{
+ OCSP_REQUEST *req;
+ OCSP_ONEREQ *one;
+ OCSP_CERTID *id;
+ VALUE ary, tmp;
+ int i, count;
+
+ GetOCSPReq(self, req);
+ count = OCSP_request_onereq_count(req);
+ ary = (count > 0) ? rb_ary_new() : Qnil;
+ for(i = 0; i < count; i++){
+ one = OCSP_request_onereq_get0(req, i);
+ if(!(id = OCSP_CERTID_dup(OCSP_onereq_get0_id(one))))
+ ossl_raise(eOCSPError, NULL);
+ WrapOCSPCertId(cOCSPCertId, tmp, id);
+ rb_ary_push(ary, tmp);
+ }
+
+ return ary;
+}
+
+static VALUE
+ossl_ocspreq_sign(int argc, VALUE *argv, VALUE self)
+{
+ VALUE signer_cert, signer_key, certs, flags;
+ OCSP_REQUEST *req;
+ X509 *signer;
+ EVP_PKEY *key;
+ STACK_OF(X509) *x509s;
+ unsigned long flg;
+ int ret;
+
+ rb_scan_args(argc, argv, "22", &signer_cert, &signer_key, &certs, &flags);
+ signer = GetX509CertPtr(signer_cert);
+ key = GetPrivPKeyPtr(signer_key);
+ flg = NIL_P(flags) ? 0 : NUM2INT(flags);
+ if(NIL_P(certs)){
+ x509s = sk_X509_new_null();
+ flags |= OCSP_NOCERTS;
+ }
+ else x509s = ossl_x509_ary2sk(certs);
+ GetOCSPReq(self, req);
+ ret = OCSP_request_sign(req, signer, key, EVP_sha1(), x509s, flg);
+ sk_X509_pop_free(x509s, X509_free);
+ if(!ret) ossl_raise(eOCSPError, NULL);
+
+ return self;
+}
+
+static VALUE
+ossl_ocspreq_verify(int argc, VALUE *argv, VALUE self)
+{
+ VALUE certs, store, flags;
+ OCSP_REQUEST *req;
+ STACK_OF(X509) *x509s;
+ X509_STORE *x509st;
+ int flg, result;
+
+ rb_scan_args(argc, argv, "21", &certs, &store, &flags);
+ x509st = GetX509StorePtr(store);
+ flg = NIL_P(flags) ? 0 : INT2NUM(flags);
+ x509s = ossl_x509_ary2sk(certs);
+ GetOCSPReq(self, req);
+ result = OCSP_request_verify(req, x509s, x509st, flg);
+ sk_X509_pop_free(x509s, X509_free);
+ if(!result) rb_warn("%s", ERR_error_string(ERR_peek_error(), NULL));
+
+ return result ? Qtrue : Qfalse;
+}
+
+static VALUE
+ossl_ocspreq_to_der(VALUE self)
+{
+ OCSP_REQUEST *req;
+ VALUE str;
+ unsigned char *p;
+ long len;
+
+ GetOCSPReq(self, req);
+ 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;
+}
+
+/*
+ * OCSP::Response
+ */
+static VALUE
+ossl_ocspres_s_create(VALUE klass, VALUE status, VALUE basic_resp)
+{
+ OCSP_BASICRESP *bs;
+ OCSP_RESPONSE *res;
+ VALUE obj;
+ int st = NUM2INT(status);
+
+ if(NIL_P(basic_resp)) bs = NULL;
+ else GetOCSPBasicRes(basic_resp, bs); /* NO NEED TO DUP */
+ if(!(res = OCSP_response_create(st, bs)))
+ ossl_raise(eOCSPError, NULL);
+ WrapOCSPRes(klass, obj, res);
+
+ return obj;
+}
+
+static VALUE
+ossl_ocspres_alloc(VALUE klass)
+{
+ OCSP_RESPONSE *res;
+ VALUE obj;
+
+ if(!(res = OCSP_RESPONSE_new()))
+ ossl_raise(eOCSPError, NULL);
+ WrapOCSPRes(klass, obj, res);
+
+ return obj;
+}
+
+static VALUE
+ossl_ocspres_initialize(int argc, VALUE *argv, VALUE self)
+{
+ VALUE arg;
+ unsigned char *p;
+
+ rb_scan_args(argc, argv, "01", &arg);
+ if(!NIL_P(arg)){
+ arg = ossl_to_der_if_possible(arg);
+ StringValue(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");
+ }
+ }
+
+ return self;
+}
+
+static VALUE
+ossl_ocspres_status(VALUE self)
+{
+ OCSP_RESPONSE *res;
+ int st;
+
+ GetOCSPRes(self, res);
+ st = OCSP_response_status(res);
+
+ return INT2NUM(st);
+}
+
+static VALUE
+ossl_ocspres_status_string(VALUE self)
+{
+ OCSP_RESPONSE *res;
+ int st;
+
+ GetOCSPRes(self, res);
+ st = OCSP_response_status(res);
+
+ return rb_str_new2(OCSP_response_status_str(st));
+}
+
+static VALUE
+ossl_ocspres_get_basic(VALUE self)
+{
+ OCSP_RESPONSE *res;
+ OCSP_BASICRESP *bs;
+ VALUE ret;
+
+ GetOCSPRes(self, res);
+ if(!(bs = OCSP_response_get1_basic(res)))
+ return Qnil;
+ WrapOCSPBasicRes(cOCSPBasicRes, ret, bs);
+
+ return ret;
+}
+
+static VALUE
+ossl_ocspres_to_der(VALUE self)
+{
+ OCSP_RESPONSE *res;
+ VALUE str;
+ long len;
+ unsigned char *p;
+
+ GetOCSPRes(self, res);
+ 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;
+}
+
+/*
+ * OCSP::BasicResponse
+ */
+static VALUE
+ossl_ocspbres_alloc(VALUE klass)
+{
+ OCSP_BASICRESP *bs;
+ VALUE obj;
+
+ if(!(bs = OCSP_BASICRESP_new()))
+ ossl_raise(eOCSPError, NULL);
+ WrapOCSPBasicRes(klass, obj, bs);
+
+ return obj;
+}
+
+static VALUE
+ossl_ocspbres_initialize(int argc, VALUE *argv, VALUE self)
+{
+ return self;
+}
+
+static VALUE
+ossl_ocspbres_copy_nonce(VALUE self, VALUE request)
+{
+ OCSP_BASICRESP *bs;
+ OCSP_REQUEST *req;
+ int ret;
+
+ GetOCSPBasicRes(self, bs);
+ SafeGetOCSPReq(request, req);
+ ret = OCSP_copy_nonce(bs, req);
+
+ return INT2NUM(ret);
+}
+
+static VALUE
+ossl_ocspbres_add_nonce(int argc, VALUE *argv, VALUE self)
+{
+ OCSP_BASICRESP *bs;
+ VALUE val;
+ int ret;
+
+ rb_scan_args(argc, argv, "01", &val);
+ if(NIL_P(val)) {
+ GetOCSPBasicRes(self, bs);
+ ret = OCSP_basic_add1_nonce(bs, NULL, -1);
+ }
+ else{
+ StringValue(val);
+ GetOCSPBasicRes(self, bs);
+ ret = OCSP_basic_add1_nonce(bs, RSTRING(val)->ptr, RSTRING(val)->len);
+ }
+ if(!ret) ossl_raise(eOCSPError, NULL);
+
+ return self;
+}
+
+static VALUE
+ossl_ocspbres_add_status(VALUE self, VALUE cid, VALUE status,
+ VALUE reason, VALUE revtime,
+ VALUE thisupd, VALUE nextupd, VALUE ext)
+{
+ OCSP_BASICRESP *bs;
+ OCSP_SINGLERESP *single;
+ OCSP_CERTID *id;
+ int st, rsn;
+ ASN1_TIME *ths, *nxt, *rev;
+ int error, i, rstatus = 0;
+ VALUE tmp;
+
+ st = NUM2INT(status);
+ rsn = NIL_P(status) ? 0 : NUM2INT(reason);
+ if(!NIL_P(ext)){
+ /* All ary's members should be X509Extension */
+ Check_Type(ext, T_ARRAY);
+ for (i = 0; i < RARRAY(ext)->len; i++)
+ OSSL_Check_Kind(RARRAY(ext)->ptr[i], cX509Ext);
+ }
+
+ error = 0;
+ ths = nxt = rev = NULL;
+ if(!NIL_P(revtime)){
+ tmp = rb_protect(rb_Integer, revtime, &rstatus);
+ if(rstatus) goto err;
+ rev = X509_gmtime_adj(NULL, NUM2INT(tmp));
+ }
+ tmp = rb_protect(rb_Integer, thisupd, &rstatus);
+ if(rstatus) goto err;
+ ths = X509_gmtime_adj(NULL, NUM2INT(tmp));
+ tmp = rb_protect(rb_Integer, nextupd, &rstatus);
+ if(rstatus) goto err;
+ nxt = X509_gmtime_adj(NULL, NUM2INT(tmp));
+
+ GetOCSPBasicRes(self, bs);
+ SafeGetOCSPCertId(cid, id);
+ if(!(single = OCSP_basic_add1_status(bs, id, st, rsn, rev, ths, nxt))){
+ error = 1;
+ goto err;
+ }
+
+ if(!NIL_P(ext)){
+ X509_EXTENSION *x509ext;
+ sk_X509_EXTENSION_pop_free(single->singleExtensions, X509_EXTENSION_free);
+ single->singleExtensions = NULL;
+ for(i = 0; i < RARRAY(ext)->len; i++){
+ x509ext = DupX509ExtPtr(RARRAY(ext)->ptr[i]);
+ if(!OCSP_SINGLERESP_add_ext(single, x509ext, -1)){
+ X509_EXTENSION_free(x509ext);
+ error = 1;
+ goto err;
+ }
+ X509_EXTENSION_free(x509ext);
+ }
+ }
+
+ err:
+ ASN1_TIME_free(ths);
+ ASN1_TIME_free(nxt);
+ ASN1_TIME_free(rev);
+ if(error) ossl_raise(eOCSPError, NULL);
+ if(rstatus) rb_jump_tag(rstatus);
+
+ return self;
+}
+
+static VALUE
+ossl_ocspbres_get_status(VALUE self)
+{
+ OCSP_BASICRESP *bs;
+ OCSP_SINGLERESP *single;
+ OCSP_CERTID *cid;
+ ASN1_TIME *revtime, *thisupd, *nextupd;
+ int status, reason;
+ X509_EXTENSION *x509ext;
+ VALUE ret, ary, ext;
+ int count, ext_count, i, j;
+
+ GetOCSPBasicRes(self, bs);
+ ret = rb_ary_new();
+ count = OCSP_resp_count(bs);
+ for(i = 0; i < count; i++){
+ single = OCSP_resp_get0(bs, i);
+ if(!single) continue;
+
+ revtime = thisupd = nextupd = NULL;
+ status = OCSP_single_get0_status(single, &reason, &revtime,
+ &thisupd, &nextupd);
+ if(status < 0) continue;
+ if(!(cid = OCSP_CERTID_dup(single->certId)))
+ ossl_raise(eOCSPError, NULL);
+ ary = rb_ary_new();
+ rb_ary_push(ary, ossl_ocspcertid_new(cid));
+ rb_ary_push(ary, INT2NUM(status));
+ rb_ary_push(ary, INT2NUM(reason));
+ rb_ary_push(ary, revtime ? asn1time_to_time(revtime) : Qnil);
+ rb_ary_push(ary, thisupd ? asn1time_to_time(thisupd) : Qnil);
+ rb_ary_push(ary, nextupd ? asn1time_to_time(nextupd) : Qnil);
+ ext = rb_ary_new();
+ ext_count = OCSP_SINGLERESP_get_ext_count(single);
+ for(j = 0; j < ext_count; j++){
+ x509ext = OCSP_SINGLERESP_get_ext(single, j);
+ rb_ary_push(ext, ossl_x509ext_new(x509ext));
+ }
+ rb_ary_push(ary, ext);
+ rb_ary_push(ret, ary);
+ }
+
+ return ret;
+}
+
+static VALUE
+ossl_ocspbres_sign(int argc, VALUE *argv, VALUE self)
+{
+ VALUE signer_cert, signer_key, certs, flags;
+ OCSP_BASICRESP *bs;
+ X509 *signer;
+ EVP_PKEY *key;
+ STACK_OF(X509) *x509s;
+ unsigned long flg;
+ int ret;
+
+ rb_scan_args(argc, argv, "22", &signer_cert, &signer_key, &certs, &flags);
+ signer = GetX509CertPtr(signer_cert);
+ key = GetPrivPKeyPtr(signer_key);
+ flg = NIL_P(flags) ? 0 : NUM2INT(flags);
+ if(NIL_P(certs)){
+ x509s = sk_X509_new_null();
+ flg |= OCSP_NOCERTS;
+ }
+ else{
+ x509s = ossl_x509_ary2sk(certs);
+ }
+ GetOCSPBasicRes(self, bs);
+ ret = OCSP_basic_sign(bs, signer, key, EVP_sha1(), x509s, flg);
+ sk_X509_pop_free(x509s, X509_free);
+ if(!ret) ossl_raise(eOCSPError, NULL);
+
+ return self;
+}
+
+static VALUE
+ossl_ocspbres_verify(int argc, VALUE *argv, VALUE self)
+{
+ VALUE certs, store, flags;
+ OCSP_BASICRESP *bs;
+ STACK_OF(X509) *x509s;
+ X509_STORE *x509st;
+ int flg, result;
+
+ rb_scan_args(argc, argv, "21", &certs, &store, &flags);
+ x509st = GetX509StorePtr(store);
+ flg = NIL_P(flags) ? 0 : INT2NUM(flags);
+ x509s = ossl_x509_ary2sk(certs);
+ GetOCSPBasicRes(self, bs);
+ result = OCSP_basic_verify(bs, x509s, x509st, flg);
+ sk_X509_pop_free(x509s, X509_free);
+ if(!result) rb_warn("%s", ERR_error_string(ERR_peek_error(), NULL));
+
+ return result ? Qtrue : Qfalse;
+}
+
+/*
+ * OCSP::CertificateId
+ */
+static VALUE
+ossl_ocspcid_alloc(VALUE klass)
+{
+ OCSP_CERTID *id;
+ VALUE obj;
+
+ if(!(id = OCSP_CERTID_new()))
+ ossl_raise(eOCSPError, NULL);
+ WrapOCSPCertId(klass, obj, id);
+
+ return obj;
+}
+
+static VALUE
+ossl_ocspcid_initialize(VALUE self, VALUE subject, VALUE issuer)
+{
+ OCSP_CERTID *id, *newid;
+ X509 *x509s, *x509i;
+
+ x509s = GetX509CertPtr(subject); /* NO NEED TO DUP */
+ x509i = GetX509CertPtr(issuer); /* NO NEED TO DUP */
+ if(!(newid = OCSP_cert_to_id(NULL, x509s, x509i)))
+ ossl_raise(eOCSPError, NULL);
+ GetOCSPCertId(self, id);
+ OCSP_CERTID_free(id);
+ RDATA(self)->data = newid;
+
+ return self;
+}
+
+static VALUE
+ossl_ocspcid_cmp(VALUE self, VALUE other)
+{
+ OCSP_CERTID *id, *id2;
+ int result;
+
+ GetOCSPCertId(self, id);
+ SafeGetOCSPCertId(other, id2);
+ result = OCSP_id_cmp(id, id2);
+
+ return (result == 0) ? Qtrue : Qfalse;
+}
+
+static VALUE
+ossl_ocspcid_cmp_issuer(VALUE self, VALUE other)
+{
+ OCSP_CERTID *id, *id2;
+ int result;
+
+ GetOCSPCertId(self, id);
+ SafeGetOCSPCertId(other, id2);
+ result = OCSP_id_issuer_cmp(id, id2);
+
+ return (result == 0) ? Qtrue : Qfalse;
+}
+
+static VALUE
+ossl_ocspcid_get_serial(VALUE self)
+{
+ OCSP_CERTID *id;
+
+ GetOCSPCertId(self, id);
+
+ return asn1integer_to_num(id->serialNumber);
+}
+
+void
+Init_ossl_ocsp()
+{
+ mOCSP = rb_define_module_under(mOSSL, "OCSP");
+
+ eOCSPError = rb_define_class_under(mOCSP, "OCSPError", rb_cObject);
+
+ cOCSPReq = rb_define_class_under(mOCSP, "Request", rb_cObject);
+ rb_define_alloc_func(cOCSPReq, ossl_ocspreq_alloc);
+ rb_define_method(cOCSPReq, "initialize", ossl_ocspreq_initialize, -1);
+ rb_define_method(cOCSPReq, "add_nonce", ossl_ocspreq_add_nonce, -1);
+ rb_define_method(cOCSPReq, "check_nonce", ossl_ocspreq_check_nonce, 1);
+ rb_define_method(cOCSPReq, "add_certid", ossl_ocspreq_add_certid, 1);
+ rb_define_method(cOCSPReq, "certid", ossl_ocspreq_get_certid, 0);
+ rb_define_method(cOCSPReq, "sign", ossl_ocspreq_sign, -1);
+ rb_define_method(cOCSPReq, "verify", ossl_ocspreq_verify, -1);
+ rb_define_method(cOCSPReq, "to_der", ossl_ocspreq_to_der, 0);
+
+ cOCSPRes = rb_define_class_under(mOCSP, "Response", rb_cObject);
+ rb_define_singleton_method(cOCSPRes, "create", ossl_ocspres_s_create, 2);
+ rb_define_alloc_func(cOCSPRes, ossl_ocspres_alloc);
+ rb_define_method(cOCSPRes, "initialize", ossl_ocspres_initialize, -1);
+ rb_define_method(cOCSPRes, "status", ossl_ocspres_status, 0);
+ rb_define_method(cOCSPRes, "status_string", ossl_ocspres_status_string, 0);
+ rb_define_method(cOCSPRes, "basic", ossl_ocspres_get_basic, 0);
+ rb_define_method(cOCSPRes, "to_der", ossl_ocspres_to_der, 0);
+
+ cOCSPBasicRes = rb_define_class_under(mOCSP, "BasicResponse", rb_cObject);
+ rb_define_alloc_func(cOCSPBasicRes, ossl_ocspbres_alloc);
+ rb_define_method(cOCSPBasicRes, "initialize", ossl_ocspbres_initialize, -1);
+ rb_define_method(cOCSPBasicRes, "copy_nonce", ossl_ocspbres_copy_nonce, 1);
+ rb_define_method(cOCSPBasicRes, "add_nonce", ossl_ocspbres_add_nonce, -1);
+ rb_define_method(cOCSPBasicRes, "add_status", ossl_ocspbres_add_status, 7);
+ rb_define_method(cOCSPBasicRes, "status", ossl_ocspbres_get_status, 0);
+ rb_define_method(cOCSPBasicRes, "sign", ossl_ocspbres_sign, -1);
+ rb_define_method(cOCSPBasicRes, "verify", ossl_ocspbres_verify, -1);
+
+ cOCSPCertId = rb_define_class_under(mOCSP, "CertificateId", rb_cObject);
+ rb_define_alloc_func(cOCSPCertId, ossl_ocspcid_alloc);
+ rb_define_method(cOCSPCertId, "initialize", ossl_ocspcid_initialize, 2);
+ rb_define_method(cOCSPCertId, "cmp", ossl_ocspcid_cmp, 1);
+ rb_define_method(cOCSPCertId, "cmp_issuer", ossl_ocspcid_cmp_issuer, 1);
+ rb_define_method(cOCSPCertId, "serial", ossl_ocspcid_get_serial, 0);
+
+#define DefOCSPConst(x) rb_define_const(mOCSP, #x, INT2NUM(OCSP_##x))
+
+ DefOCSPConst(RESPONSE_STATUS_SUCCESSFUL);
+ DefOCSPConst(RESPONSE_STATUS_MALFORMEDREQUEST);
+ DefOCSPConst(RESPONSE_STATUS_INTERNALERROR);
+ DefOCSPConst(RESPONSE_STATUS_TRYLATER);
+ DefOCSPConst(RESPONSE_STATUS_SIGREQUIRED);
+ DefOCSPConst(RESPONSE_STATUS_UNAUTHORIZED);
+
+ DefOCSPConst(REVOKED_STATUS_NOSTATUS);
+ DefOCSPConst(REVOKED_STATUS_UNSPECIFIED);
+ DefOCSPConst(REVOKED_STATUS_KEYCOMPROMISE);
+ DefOCSPConst(REVOKED_STATUS_CACOMPROMISE);
+ DefOCSPConst(REVOKED_STATUS_AFFILIATIONCHANGED);
+ DefOCSPConst(REVOKED_STATUS_SUPERSEDED);
+ DefOCSPConst(REVOKED_STATUS_CESSATIONOFOPERATION);
+ DefOCSPConst(REVOKED_STATUS_CERTIFICATEHOLD);
+ DefOCSPConst(REVOKED_STATUS_REMOVEFROMCRL);
+
+ DefOCSPConst(NOCERTS);
+ DefOCSPConst(NOINTERN);
+ DefOCSPConst(NOSIGS);
+ DefOCSPConst(NOCHAIN);
+ DefOCSPConst(NOVERIFY);
+ DefOCSPConst(NOEXPLICIT);
+ DefOCSPConst(NOCASIGN);
+ DefOCSPConst(NODELEGATED);
+ DefOCSPConst(NOCHECKS);
+ DefOCSPConst(TRUSTOTHER);
+ DefOCSPConst(RESPID_KEY);
+ DefOCSPConst(NOTIME);
+
+#define DefOCSPVConst(x) rb_define_const(mOCSP, "V_" #x, INT2NUM(V_OCSP_##x))
+
+ DefOCSPVConst(CERTSTATUS_GOOD);
+ DefOCSPVConst(CERTSTATUS_REVOKED);
+ DefOCSPVConst(CERTSTATUS_UNKNOWN);
+ DefOCSPVConst(RESPID_NAME);
+ DefOCSPVConst(RESPID_KEY);
+}
+
+#else /* ! OSSL_OCSP_ENABLED */
+void
+Init_ossl_ocsp()
+{
+}
+#endif
diff --git a/ruby_1_8_5/ext/openssl/ossl_ocsp.h b/ruby_1_8_5/ext/openssl/ossl_ocsp.h
new file mode 100644
index 0000000000..244fbb2a74
--- /dev/null
+++ b/ruby_1_8_5/ext/openssl/ossl_ocsp.h
@@ -0,0 +1,24 @@
+/*
+ * $Id: ossl_ocsp.h,v 1.1 2003/07/23 16:11:29 gotoyuzo Exp $
+ * 'OpenSSL for Ruby' project
+ * Copyright (C) 2003 Michal Rokos <m.rokos@sh.cvut.cz>
+ * Copyright (C) 2003 GOTOU Yuuzou <gotoyuzo@notwork.org>
+ * All rights reserved.
+ */
+/*
+ * This program is licenced under the same licence as Ruby.
+ * (See the file 'LICENCE'.)
+ */
+#if !defined(_OSSL_OCSP_H_)
+#define _OSSL_OCSP_H_
+
+#if defined(OSSL_OCSP_ENABLED)
+extern VALUE mOCSP;
+extern VALUE cOPCSReq;
+extern VALUE cOPCSRes;
+extern VALUE cOPCSBasicRes;
+#endif
+
+void Init_ossl_ocsp(void);
+
+#endif /* _OSSL_OCSP_H_ */
diff --git a/ruby_1_8_5/ext/openssl/ossl_pkcs12.c b/ruby_1_8_5/ext/openssl/ossl_pkcs12.c
new file mode 100644
index 0000000000..e4b334c67e
--- /dev/null
+++ b/ruby_1_8_5/ext/openssl/ossl_pkcs12.c
@@ -0,0 +1,154 @@
+/*
+ * This program is licenced under the same licence as Ruby.
+ * (See the file 'LICENCE'.)
+ * $Id: ossl_pkcs12.c,v 1.2 2003/12/15 00:30:12 usa Exp $
+ */
+#include "ossl.h"
+
+#define WrapPKCS12(klass, obj, p12) do { \
+ if(!p12) ossl_raise(rb_eRuntimeError, "PKCS12 wasn't initialized."); \
+ obj = Data_Wrap_Struct(klass, 0, PKCS12_free, p12); \
+} while (0)
+
+#define GetPKCS12(obj, p12) do { \
+ Data_Get_Struct(obj, PKCS12, p12); \
+ if(!p12) ossl_raise(rb_eRuntimeError, "PKCS12 wasn't initialized."); \
+} while (0)
+
+#define SafeGetPKCS12(obj, p12) do { \
+ OSSL_Check_Kind(obj, cPKCS12); \
+ GetPKCS12(obj, p12); \
+} while (0)
+
+#define ossl_pkcs12_set_key(o,v) rb_iv_set((o), "@key", (v))
+#define ossl_pkcs12_set_cert(o,v) rb_iv_set((o), "@certificate", (v))
+#define ossl_pkcs12_set_ca_certs(o,v) rb_iv_set((o), "@ca_certs", (v))
+#define ossl_pkcs12_get_key(o) rb_iv_get((o), "@key")
+#define ossl_pkcs12_get_cert(o) rb_iv_get((o), "@certificate")
+#define ossl_pkcs12_get_ca_certs(o) rb_iv_get((o), "@ca_certs")
+
+/*
+ * Classes
+ */
+VALUE mPKCS12;
+VALUE cPKCS12;
+VALUE ePKCS12Error;
+
+/*
+ * Private
+ */
+static VALUE
+ossl_pkcs12_s_allocate(VALUE klass)
+{
+ PKCS12 *p12;
+ VALUE obj;
+
+ if(!(p12 = PKCS12_new())) ossl_raise(ePKCS12Error, NULL);
+ WrapPKCS12(klass, obj, p12);
+
+ return obj;
+}
+
+static VALUE
+ossl_pkcs12_s_create(int argc, VALUE *argv, VALUE self)
+{
+ VALUE pass, name, pkey, cert, ca;
+ VALUE obj;
+ char *passphrase, *friendlyname;
+ EVP_PKEY *key;
+ X509 *x509;
+ STACK_OF(X509) *x509s;
+ PKCS12 *p12;
+
+ rb_scan_args(argc, argv, "41", &pass, &name, &pkey, &cert, &ca);
+ passphrase = NIL_P(pass) ? NULL : StringValuePtr(pass);
+ friendlyname = NIL_P(name) ? NULL : StringValuePtr(name);
+ key = GetPKeyPtr(pkey);
+ x509 = GetX509CertPtr(cert);
+ x509s = NIL_P(ca) ? NULL : ossl_x509_ary2sk(ca);
+ p12 = PKCS12_create(passphrase, friendlyname, key, x509, x509s,
+ 0, 0, 0, 0, 0);
+ sk_X509_pop_free(x509s, X509_free);
+ if(!p12) ossl_raise(ePKCS12Error, NULL);
+ WrapPKCS12(cPKCS12, obj, p12);
+
+ return obj;
+}
+
+static VALUE
+ossl_pkcs12_initialize(int argc, VALUE *argv, VALUE self)
+{
+ BIO *in;
+ VALUE arg, pass, pkey, cert, ca;
+ char *passphrase;
+ EVP_PKEY *key;
+ X509 *x509;
+ STACK_OF(X509) *x509s = NULL;
+ int st = 0;
+
+ if(rb_scan_args(argc, argv, "02", &arg, &pass) == 0) return self;
+ passphrase = NIL_P(pass) ? NULL : StringValuePtr(pass);
+ in = ossl_obj2bio(arg);
+ d2i_PKCS12_bio(in, (PKCS12 **)&DATA_PTR(self));
+ BIO_free(in);
+
+ pkey = cert = ca = Qnil;
+ if(!PKCS12_parse((PKCS12*)DATA_PTR(self), passphrase, &key, &x509, &x509s))
+ ossl_raise(ePKCS12Error, NULL);
+ pkey = rb_protect((VALUE(*)_((VALUE)))ossl_pkey_new, (VALUE)key,
+ &st); /* NO DUP */
+ if(st) goto err;
+ cert = rb_protect((VALUE(*)_((VALUE)))ossl_x509_new, (VALUE)x509, &st);
+ if(st) goto err;
+ if(x509s){
+ ca =
+ rb_protect((VALUE(*)_((VALUE)))ossl_x509_sk2ary, (VALUE)x509s, &st);
+ if(st) goto err;
+ }
+
+ err:
+ X509_free(x509);
+ sk_X509_pop_free(x509s, X509_free);
+ ossl_pkcs12_set_key(self, pkey);
+ ossl_pkcs12_set_cert(self, cert);
+ ossl_pkcs12_set_ca_certs(self, ca);
+ if(st) rb_jump_tag(st);
+
+ return self;
+}
+
+static VALUE
+ossl_pkcs12_to_der(VALUE self)
+{
+ PKCS12 *p12;
+ VALUE str;
+ long len;
+ unsigned char *p;
+
+ GetPKCS12(self, p12);
+ if((len = i2d_PKCS12(p12, NULL)) <= 0)
+ ossl_raise(ePKCS12Error, NULL);
+ str = rb_str_new(0, len);
+ p = RSTRING(str)->ptr;
+ if(i2d_PKCS12(p12, &p) <= 0)
+ ossl_raise(ePKCS12Error, NULL);
+ ossl_str_adjust(str, p);
+
+ return str;
+}
+
+void
+Init_ossl_pkcs12()
+{
+ mPKCS12 = rb_define_module_under(mOSSL, "PKCS12");
+ cPKCS12 = rb_define_class_under(mPKCS12, "PKCS12", rb_cObject);
+ ePKCS12Error = rb_define_class_under(mPKCS12, "PKCS12Error", eOSSLError);
+ rb_define_module_function(mPKCS12, "create", ossl_pkcs12_s_create, -1);
+
+ rb_define_alloc_func(cPKCS12, ossl_pkcs12_s_allocate);
+ rb_attr(cPKCS12, rb_intern("key"), 1, 0, Qfalse);
+ rb_attr(cPKCS12, rb_intern("certificate"), 1, 0, Qfalse);
+ rb_attr(cPKCS12, rb_intern("ca_certs"), 1, 0, Qfalse);
+ rb_define_method(cPKCS12, "initialize", ossl_pkcs12_initialize, -1);
+ rb_define_method(cPKCS12, "to_der", ossl_pkcs12_to_der, 0);
+}
diff --git a/ruby_1_8_5/ext/openssl/ossl_pkcs12.h b/ruby_1_8_5/ext/openssl/ossl_pkcs12.h
new file mode 100644
index 0000000000..95b29de9b5
--- /dev/null
+++ b/ruby_1_8_5/ext/openssl/ossl_pkcs12.h
@@ -0,0 +1,16 @@
+/*
+ * This program is licenced under the same licence as Ruby.
+ * (See the file 'LICENCE'.)
+ * $Id: ossl_pkcs12.h,v 1.1.2.1 2005/06/19 16:29:17 gotoyuzo Exp $
+ */
+#if !defined(_OSSL_PKCS12_H_)
+#define _OSSL_PKCS12_H_
+
+extern VALUE mPKCS12;
+extern VALUE cPKCS12;
+extern VALUE ePKCS12Error;
+
+void Init_ossl_pkcs12(void);
+
+#endif /* _OSSL_PKCS12_H_ */
+
diff --git a/ruby_1_8_5/ext/openssl/ossl_pkcs5.h b/ruby_1_8_5/ext/openssl/ossl_pkcs5.h
new file mode 100644
index 0000000000..a3b132bc50
--- /dev/null
+++ b/ruby_1_8_5/ext/openssl/ossl_pkcs5.h
@@ -0,0 +1,6 @@
+#if !defined(_OSSL_PKCS5_H_)
+#define _OSSL_PKCS5_H_
+
+void Init_ossl_pkcs5(void);
+
+#endif /* _OSSL_PKCS5_H_ */
diff --git a/ruby_1_8_5/ext/openssl/ossl_pkcs7.c b/ruby_1_8_5/ext/openssl/ossl_pkcs7.c
new file mode 100644
index 0000000000..0fa85299aa
--- /dev/null
+++ b/ruby_1_8_5/ext/openssl/ossl_pkcs7.c
@@ -0,0 +1,993 @@
+/*
+ * $Id: ossl_pkcs7.c,v 1.5.2.3 2005/09/10 01:11:15 gotoyuzo Exp $
+ * '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'.)
+ */
+#include "ossl.h"
+
+#define WrapPKCS7(klass, obj, pkcs7) do { \
+ if (!pkcs7) { \
+ ossl_raise(rb_eRuntimeError, "PKCS7 wasn't initialized."); \
+ } \
+ obj = Data_Wrap_Struct(klass, 0, PKCS7_free, pkcs7); \
+} while (0)
+#define GetPKCS7(obj, pkcs7) do { \
+ Data_Get_Struct(obj, PKCS7, pkcs7); \
+ if (!pkcs7) { \
+ ossl_raise(rb_eRuntimeError, "PKCS7 wasn't initialized."); \
+ } \
+} while (0)
+#define SafeGetPKCS7(obj, pkcs7) do { \
+ OSSL_Check_Kind(obj, cPKCS7); \
+ GetPKCS7(obj, pkcs7); \
+} while (0)
+
+#define WrapPKCS7si(klass, obj, p7si) do { \
+ if (!p7si) { \
+ ossl_raise(rb_eRuntimeError, "PKCS7si wasn't initialized."); \
+ } \
+ obj = Data_Wrap_Struct(klass, 0, PKCS7_SIGNER_INFO_free, p7si); \
+} while (0)
+#define GetPKCS7si(obj, p7si) do { \
+ Data_Get_Struct(obj, PKCS7_SIGNER_INFO, p7si); \
+ if (!p7si) { \
+ ossl_raise(rb_eRuntimeError, "PKCS7si wasn't initialized."); \
+ } \
+} while (0)
+#define SafeGetPKCS7si(obj, p7si) do { \
+ OSSL_Check_Kind(obj, cPKCS7Signer); \
+ GetPKCS7si(obj, p7si); \
+} while (0)
+
+#define WrapPKCS7ri(klass, obj, p7ri) do { \
+ if (!p7ri) { \
+ ossl_raise(rb_eRuntimeError, "PKCS7ri wasn't initialized."); \
+ } \
+ obj = Data_Wrap_Struct(klass, 0, PKCS7_RECIP_INFO_free, p7ri); \
+} while (0)
+#define GetPKCS7ri(obj, p7ri) do { \
+ Data_Get_Struct(obj, PKCS7_RECIP_INFO, p7ri); \
+ if (!p7ri) { \
+ ossl_raise(rb_eRuntimeError, "PKCS7ri wasn't initialized."); \
+ } \
+} while (0)
+#define SafeGetPKCS7ri(obj, p7ri) do { \
+ OSSL_Check_Kind(obj, cPKCS7Recipient); \
+ GetPKCS7ri(obj, p7ri); \
+} while (0)
+
+#define numberof(ary) (sizeof(ary)/sizeof(ary[0]))
+
+#define ossl_pkcs7_set_data(o,v) rb_iv_set((o), "@data", (v))
+#define ossl_pkcs7_get_data(o) rb_iv_get((o), "@data")
+#define ossl_pkcs7_set_err_string(o,v) rb_iv_set((o), "@error_string", (v))
+#define ossl_pkcs7_get_err_string(o) rb_iv_get((o), "@error_string")
+
+/*
+ * Classes
+ */
+VALUE mPKCS7;
+VALUE cPKCS7;
+VALUE cPKCS7Signer;
+VALUE cPKCS7Recipient;
+VALUE ePKCS7Error;
+
+/*
+ * Public
+ * (MADE PRIVATE UNTIL SOMEBODY WILL NEED THEM)
+ */
+static VALUE
+ossl_pkcs7si_new(PKCS7_SIGNER_INFO *p7si)
+{
+ PKCS7_SIGNER_INFO *pkcs7;
+ VALUE obj;
+
+ pkcs7 = p7si ? PKCS7_SIGNER_INFO_dup(p7si) : PKCS7_SIGNER_INFO_new();
+ if (!pkcs7) ossl_raise(ePKCS7Error, NULL);
+ WrapPKCS7si(cPKCS7Signer, obj, pkcs7);
+
+ return obj;
+}
+
+static PKCS7_SIGNER_INFO *
+DupPKCS7SignerPtr(VALUE obj)
+{
+ PKCS7_SIGNER_INFO *p7si, *pkcs7;
+
+ SafeGetPKCS7si(obj, p7si);
+ if (!(pkcs7 = PKCS7_SIGNER_INFO_dup(p7si))) {
+ ossl_raise(ePKCS7Error, NULL);
+ }
+
+ return pkcs7;
+}
+
+static VALUE
+ossl_pkcs7ri_new(PKCS7_RECIP_INFO *p7ri)
+{
+ PKCS7_RECIP_INFO *pkcs7;
+ VALUE obj;
+
+ pkcs7 = p7ri ? PKCS7_RECIP_INFO_dup(p7ri) : PKCS7_RECIP_INFO_new();
+ if (!pkcs7) ossl_raise(ePKCS7Error, NULL);
+ WrapPKCS7ri(cPKCS7Recipient, obj, pkcs7);
+
+ return obj;
+}
+
+static PKCS7_RECIP_INFO *
+DupPKCS7RecipientPtr(VALUE obj)
+{
+ PKCS7_RECIP_INFO *p7ri, *pkcs7;
+
+ SafeGetPKCS7ri(obj, p7ri);
+ if (!(pkcs7 = PKCS7_RECIP_INFO_dup(p7ri))) {
+ ossl_raise(ePKCS7Error, NULL);
+ }
+
+ return pkcs7;
+}
+
+/*
+ * Private
+ */
+static VALUE
+ossl_pkcs7_s_read_smime(VALUE klass, VALUE arg)
+{
+ BIO *in, *out;
+ PKCS7 *pkcs7;
+ VALUE ret, data;
+
+ in = ossl_obj2bio(arg);
+ out = NULL;
+ pkcs7 = SMIME_read_PKCS7(in, &out);
+ BIO_free(in);
+ 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);
+
+ return ret;
+}
+
+static VALUE
+ossl_pkcs7_s_write_smime(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE pkcs7, data, flags;
+ BIO *out, *in;
+ PKCS7 *p7;
+ VALUE str;
+ int flg;
+
+ rb_scan_args(argc, argv, "12", &pkcs7, &data, &flags);
+ flg = NIL_P(flags) ? 0 : NUM2INT(flags);
+ if(NIL_P(data)) data = ossl_pkcs7_get_data(pkcs7);
+ SafeGetPKCS7(pkcs7, p7);
+ if(!NIL_P(data) && PKCS7_is_detached(p7))
+ flg |= PKCS7_DETACHED;
+ in = NIL_P(data) ? NULL : ossl_obj2bio(data);
+ if(!(out = BIO_new(BIO_s_mem()))){
+ BIO_free(in);
+ ossl_raise(ePKCS7Error, NULL);
+ }
+ if(!SMIME_write_PKCS7(out, p7, in, flg)){
+ BIO_free(out);
+ BIO_free(in);
+ ossl_raise(ePKCS7Error, NULL);
+ }
+ BIO_free(in);
+ str = ossl_membio2str(out);
+
+ return str;
+}
+
+static VALUE
+ossl_pkcs7_s_sign(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE cert, key, data, certs, flags;
+ X509 *x509;
+ EVP_PKEY *pkey;
+ BIO *in;
+ STACK_OF(X509) *x509s;
+ int flg, status = 0;
+ PKCS7 *pkcs7;
+ VALUE ret;
+
+ rb_scan_args(argc, argv, "32", &cert, &key, &data, &certs, &flags);
+ x509 = GetX509CertPtr(cert); /* NO NEED TO DUP */
+ pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */
+ flg = NIL_P(flags) ? 0 : NUM2INT(flags);
+ in = ossl_obj2bio(data);
+ if(NIL_P(certs)) x509s = NULL;
+ else{
+ x509s = ossl_protect_x509_ary2sk(certs, &status);
+ if(status){
+ BIO_free(in);
+ rb_jump_tag(status);
+ }
+ }
+ if(!(pkcs7 = PKCS7_sign(x509, pkey, x509s, in, flg))){
+ BIO_free(in);
+ sk_X509_pop_free(x509s, X509_free);
+ ossl_raise(ePKCS7Error, NULL);
+ }
+ WrapPKCS7(cPKCS7, ret, pkcs7);
+ ossl_pkcs7_set_data(ret, data);
+ ossl_pkcs7_set_err_string(ret, Qnil);
+ BIO_free(in);
+ sk_X509_pop_free(x509s, X509_free);
+
+ return ret;
+}
+
+static VALUE
+ossl_pkcs7_s_encrypt(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE certs, data, cipher, flags;
+ STACK_OF(X509) *x509s;
+ BIO *in;
+ const EVP_CIPHER *ciph;
+ int flg, status = 0;
+ VALUE ret;
+ PKCS7 *p7;
+
+ rb_scan_args(argc, argv, "22", &certs, &data, &cipher, &flags);
+ if(NIL_P(cipher)){
+#if !defined(OPENSSL_NO_RC2)
+ ciph = EVP_rc2_40_cbc();
+#elif !defined(OPENSSL_NO_DES)
+ ciph = EVP_des_ede3_cbc();
+#elif !defined(OPENSSL_NO_RC2)
+ ciph = EVP_rc2_40_cbc();
+#elif !defined(OPENSSL_NO_AES)
+ ciph = EVP_EVP_aes_128_cbc();
+#else
+ ossl_raise(ePKCS7Error, "Must specify cipher");
+#endif
+
+ }
+ else ciph = GetCipherPtr(cipher); /* NO NEED TO DUP */
+ flg = NIL_P(flags) ? 0 : NUM2INT(flags);
+ in = ossl_obj2bio(data);
+ x509s = ossl_protect_x509_ary2sk(certs, &status);
+ if(status){
+ BIO_free(in);
+ rb_jump_tag(status);
+ }
+ if(!(p7 = PKCS7_encrypt(x509s, in, (EVP_CIPHER*)ciph, flg))){
+ BIO_free(in);
+ sk_X509_pop_free(x509s, X509_free);
+ ossl_raise(ePKCS7Error, NULL);
+ }
+ BIO_free(in);
+ WrapPKCS7(cPKCS7, ret, p7);
+ ossl_pkcs7_set_data(ret, data);
+ sk_X509_pop_free(x509s, X509_free);
+
+ return ret;
+}
+
+static VALUE
+ossl_pkcs7_alloc(VALUE klass)
+{
+ PKCS7 *pkcs7;
+ VALUE obj;
+
+ if (!(pkcs7 = PKCS7_new())) {
+ ossl_raise(ePKCS7Error, NULL);
+ }
+ WrapPKCS7(klass, obj, pkcs7);
+
+ return obj;
+}
+
+static VALUE
+ossl_pkcs7_initialize(int argc, VALUE *argv, VALUE self)
+{
+ PKCS7 *p7;
+ BIO *in;
+ VALUE arg;
+
+ if(rb_scan_args(argc, argv, "01", &arg) == 0)
+ return self;
+ 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);
+ ossl_pkcs7_set_err_string(self, Qnil);
+
+ return self;
+}
+
+static VALUE
+ossl_pkcs7_copy(VALUE self, VALUE other)
+{
+ PKCS7 *a, *b, *pkcs7;
+
+ rb_check_frozen(self);
+ if (self == other) return self;
+
+ GetPKCS7(self, a);
+ SafeGetPKCS7(other, b);
+
+ pkcs7 = PKCS7_dup(b);
+ if (!pkcs7) {
+ ossl_raise(ePKCS7Error, NULL);
+ }
+ DATA_PTR(self) = pkcs7;
+ PKCS7_free(a);
+
+ return self;
+}
+
+static int
+ossl_pkcs7_sym2typeid(VALUE sym)
+{
+ int i, ret = Qnil;
+ char *s;
+
+ static struct {
+ const char *name;
+ int nid;
+ } p7_type_tab[] = {
+ { "signed", NID_pkcs7_signed },
+ { "data", NID_pkcs7_data },
+ { "signedAndEnveloped", NID_pkcs7_signedAndEnveloped },
+ { "enveloped", NID_pkcs7_enveloped },
+ { "encrypted", NID_pkcs7_encrypted },
+ { "digest", NID_pkcs7_digest },
+ { NULL, 0 },
+ };
+
+ if(TYPE(sym) == T_SYMBOL) s = rb_id2name(SYM2ID(sym));
+ else s = StringValuePtr(sym);
+ for(i = 0; i < numberof(p7_type_tab); i++){
+ if(p7_type_tab[i].name == NULL)
+ ossl_raise(ePKCS7Error, "unknown type \"%s\"", s);
+ if(strcmp(p7_type_tab[i].name, s) == 0){
+ ret = p7_type_tab[i].nid;
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static VALUE
+ossl_pkcs7_set_type(VALUE self, VALUE type)
+{
+ PKCS7 *p7;
+
+ GetPKCS7(self, p7);
+ if(!PKCS7_set_type(p7, ossl_pkcs7_sym2typeid(type)))
+ ossl_raise(ePKCS7Error, NULL);
+
+ return type;
+}
+
+static VALUE
+ossl_pkcs7_get_type(VALUE self)
+{
+ PKCS7 *p7;
+
+ GetPKCS7(self, p7);
+ if(PKCS7_type_is_signed(p7))
+ return ID2SYM(rb_intern("signed"));
+ if(PKCS7_type_is_encrypted(p7))
+ return ID2SYM(rb_intern("encrypted"));
+ if(PKCS7_type_is_enveloped(p7))
+ return ID2SYM(rb_intern("enveloped"));
+ if(PKCS7_type_is_signedAndEnveloped(p7))
+ return ID2SYM(rb_intern("signedAndEnveloped"));
+ if(PKCS7_type_is_data(p7))
+ return ID2SYM(rb_intern("data"));
+ return Qnil;
+}
+
+static VALUE
+ossl_pkcs7_set_detached(VALUE self, VALUE flag)
+{
+ PKCS7 *p7;
+
+ GetPKCS7(self, p7);
+ if(flag != Qtrue && flag != Qfalse)
+ ossl_raise(ePKCS7Error, "must specify a boolean");
+ if(!PKCS7_set_detached(p7, flag == Qtrue ? 1 : 0))
+ ossl_raise(ePKCS7Error, NULL);
+
+ return flag;
+}
+
+static VALUE
+ossl_pkcs7_get_detached(VALUE self)
+{
+ PKCS7 *p7;
+ GetPKCS7(self, p7);
+ return PKCS7_get_detached(p7) ? Qtrue : Qfalse;
+}
+
+static VALUE
+ossl_pkcs7_detached_p(VALUE self)
+{
+ PKCS7 *p7;
+ GetPKCS7(self, p7);
+ return PKCS7_is_detached(p7) ? Qtrue : Qfalse;
+}
+
+static VALUE
+ossl_pkcs7_set_cipher(VALUE self, VALUE cipher)
+{
+ PKCS7 *pkcs7;
+
+ GetPKCS7(self, pkcs7);
+ if (!PKCS7_set_cipher(pkcs7, GetCipherPtr(cipher))) {
+ ossl_raise(ePKCS7Error, NULL);
+ }
+
+ return cipher;
+}
+
+static VALUE
+ossl_pkcs7_add_signer(VALUE self, VALUE signer)
+{
+ PKCS7 *pkcs7;
+ PKCS7_SIGNER_INFO *p7si;
+
+ p7si = DupPKCS7SignerPtr(signer); /* NEED TO DUP */
+ GetPKCS7(self, pkcs7);
+ if (!PKCS7_add_signer(pkcs7, p7si)) {
+ PKCS7_SIGNER_INFO_free(p7si);
+ ossl_raise(ePKCS7Error, "Could not add signer.");
+ }
+ if (PKCS7_type_is_signed(pkcs7)){
+ PKCS7_add_signed_attribute(p7si, NID_pkcs9_contentType,
+ V_ASN1_OBJECT, OBJ_nid2obj(NID_pkcs7_data));
+ }
+
+ return self;
+}
+
+static VALUE
+ossl_pkcs7_get_signer(VALUE self)
+{
+ PKCS7 *pkcs7;
+ STACK_OF(PKCS7_SIGNER_INFO) *sk;
+ PKCS7_SIGNER_INFO *si;
+ int num, i;
+ VALUE ary;
+
+ GetPKCS7(self, pkcs7);
+ if (!(sk = PKCS7_get_signer_info(pkcs7))) {
+ OSSL_Debug("OpenSSL::PKCS7#get_signer_info == NULL!");
+ return rb_ary_new();
+ }
+ if ((num = sk_PKCS7_SIGNER_INFO_num(sk)) < 0) {
+ ossl_raise(ePKCS7Error, "Negative number of signers!");
+ }
+ ary = rb_ary_new2(num);
+ for (i=0; i<num; i++) {
+ si = sk_PKCS7_SIGNER_INFO_value(sk, i);
+ rb_ary_push(ary, ossl_pkcs7si_new(si));
+ }
+
+ return ary;
+}
+
+static VALUE
+ossl_pkcs7_add_recipient(VALUE self, VALUE recip)
+{
+ PKCS7 *pkcs7;
+ PKCS7_RECIP_INFO *ri;
+
+ ri = DupPKCS7RecipientPtr(recip); /* NEED TO DUP */
+ GetPKCS7(self, pkcs7);
+ if (!PKCS7_add_recipient_info(pkcs7, ri)) {
+ PKCS7_RECIP_INFO_free(ri);
+ ossl_raise(ePKCS7Error, "Could not add recipient.");
+ }
+
+ return self;
+}
+
+static VALUE
+ossl_pkcs7_get_recipient(VALUE self)
+{
+ PKCS7 *pkcs7;
+ STACK_OF(PKCS7_RECIP_INFO) *sk;
+ PKCS7_RECIP_INFO *si;
+ int num, i;
+ VALUE ary;
+
+ GetPKCS7(self, pkcs7);
+ if (PKCS7_type_is_enveloped(pkcs7))
+ sk = pkcs7->d.enveloped->recipientinfo;
+ else if (PKCS7_type_is_signedAndEnveloped(pkcs7))
+ sk = pkcs7->d.signed_and_enveloped->recipientinfo;
+ else sk = NULL;
+ if (!sk) return rb_ary_new();
+ if ((num = sk_PKCS7_RECIP_INFO_num(sk)) < 0) {
+ ossl_raise(ePKCS7Error, "Negative number of recipient!");
+ }
+ ary = rb_ary_new2(num);
+ for (i=0; i<num; i++) {
+ si = sk_PKCS7_RECIP_INFO_value(sk, i);
+ rb_ary_push(ary, ossl_pkcs7ri_new(si));
+ }
+
+ return ary;
+}
+
+static VALUE
+ossl_pkcs7_add_certificate(VALUE self, VALUE cert)
+{
+ PKCS7 *pkcs7;
+ X509 *x509;
+
+ GetPKCS7(self, pkcs7);
+ x509 = GetX509CertPtr(cert); /* NO NEED TO DUP */
+ if (!PKCS7_add_certificate(pkcs7, x509)){
+ ossl_raise(ePKCS7Error, NULL);
+ }
+
+ return self;
+}
+
+static STACK *
+pkcs7_get_certs_or_crls(VALUE self, int want_certs)
+{
+ PKCS7 *pkcs7;
+ STACK_OF(X509) *certs;
+ STACK_OF(X509_CRL) *crls;
+ int i;
+
+ GetPKCS7(self, pkcs7);
+ i = OBJ_obj2nid(pkcs7->type);
+ switch(i){
+ case NID_pkcs7_signed:
+ certs = pkcs7->d.sign->cert;
+ crls = pkcs7->d.sign->crl;
+ break;
+ case NID_pkcs7_signedAndEnveloped:
+ certs = pkcs7->d.signed_and_enveloped->cert;
+ crls = pkcs7->d.signed_and_enveloped->crl;
+ break;
+ default:
+ certs = crls = NULL;
+ }
+
+ return want_certs ? certs : crls;
+}
+
+static VALUE
+ossl_pkcs7_set_certs_i(VALUE i, VALUE arg)
+{
+ return ossl_pkcs7_add_certificate(arg, i);
+}
+
+static VALUE
+ossl_pkcs7_set_certificates(VALUE self, VALUE ary)
+{
+ STACK_OF(X509) *certs;
+ X509 *cert;
+
+ certs = pkcs7_get_certs_or_crls(self, 1);
+ while((cert = sk_X509_pop(certs))) X509_free(cert);
+ rb_iterate(rb_each, ary, ossl_pkcs7_set_certs_i, self);
+
+ return ary;
+}
+
+static VALUE
+ossl_pkcs7_get_certificates(VALUE self)
+{
+ return ossl_x509_sk2ary(pkcs7_get_certs_or_crls(self, 1));
+}
+
+static VALUE
+ossl_pkcs7_add_crl(VALUE self, VALUE crl)
+{
+ PKCS7 *pkcs7;
+ X509_CRL *x509crl;
+
+ GetPKCS7(self, pkcs7); /* NO DUP needed! */
+ x509crl = GetX509CRLPtr(crl);
+ if (!PKCS7_add_crl(pkcs7, x509crl)) {
+ ossl_raise(ePKCS7Error, NULL);
+ }
+
+ return self;
+}
+
+static VALUE
+ossl_pkcs7_set_crls_i(VALUE i, VALUE arg)
+{
+ return ossl_pkcs7_add_crl(arg, i);
+}
+
+static VALUE
+ossl_pkcs7_set_crls(VALUE self, VALUE ary)
+{
+ STACK_OF(X509_CRL) *crls;
+ X509_CRL *crl;
+
+ crls = pkcs7_get_certs_or_crls(self, 0);
+ while((crl = sk_X509_CRL_pop(crls))) X509_CRL_free(crl);
+ rb_iterate(rb_each, ary, ossl_pkcs7_set_crls_i, self);
+
+ return ary;
+}
+
+static VALUE
+ossl_pkcs7_get_crls(VALUE self)
+{
+ return ossl_x509crl_sk2ary(pkcs7_get_certs_or_crls(self, 0));
+}
+
+static VALUE
+ossl_pkcs7_verify(int argc, VALUE *argv, VALUE self)
+{
+ VALUE certs, store, indata, flags;
+ STACK_OF(X509) *x509s;
+ X509_STORE *x509st;
+ int flg, ok, status = 0;
+ BIO *in, *out;
+ PKCS7 *p7;
+ VALUE data;
+ const char *msg;
+
+ rb_scan_args(argc, argv, "22", &certs, &store, &indata, &flags);
+ flg = NIL_P(flags) ? 0 : NUM2INT(flags);
+ if(NIL_P(indata)) indata = ossl_pkcs7_get_data(self);
+ in = NIL_P(indata) ? NULL : ossl_obj2bio(indata);
+ if(NIL_P(certs)) x509s = NULL;
+ else{
+ x509s = ossl_protect_x509_ary2sk(certs, &status);
+ if(status){
+ BIO_free(in);
+ rb_jump_tag(status);
+ }
+ }
+ x509st = GetX509StorePtr(store);
+ GetPKCS7(self, p7);
+ if(!(out = BIO_new(BIO_s_mem()))){
+ BIO_free(in);
+ sk_X509_pop_free(x509s, X509_free);
+ 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_membio2str(out);
+ ossl_pkcs7_set_data(self, data);
+ sk_X509_pop_free(x509s, X509_free);
+
+ return (ok == 1) ? Qtrue : Qfalse;
+}
+
+static VALUE
+ossl_pkcs7_decrypt(int argc, VALUE *argv, VALUE self)
+{
+ VALUE pkey, cert, flags;
+ EVP_PKEY *key;
+ X509 *x509;
+ int flg;
+ PKCS7 *p7;
+ BIO *out;
+ VALUE str;
+
+ rb_scan_args(argc, argv, "21", &pkey, &cert, &flags);
+ key = GetPrivPKeyPtr(pkey); /* NO NEED TO DUP */
+ x509 = GetX509CertPtr(cert); /* NO NEED TO DUP */
+ flg = NIL_P(flags) ? 0 : NUM2INT(flags);
+ GetPKCS7(self, p7);
+ if(!(out = BIO_new(BIO_s_mem())))
+ ossl_raise(ePKCS7Error, NULL);
+ if(!PKCS7_decrypt(p7, key, x509, out, flg)){
+ BIO_free(out);
+ ossl_raise(ePKCS7Error, NULL);
+ }
+ str = ossl_membio2str(out); /* out will be free */
+
+ return str;
+}
+
+static VALUE
+ossl_pkcs7_add_data(VALUE self, VALUE data)
+{
+ PKCS7 *pkcs7;
+ BIO *out, *in;
+ char buf[4096];
+ int len;
+
+ in = ossl_obj2bio(data);
+ GetPKCS7(self, pkcs7);
+ if(PKCS7_type_is_signed(pkcs7)){
+ if(!PKCS7_content_new(pkcs7, NID_pkcs7_data))
+ ossl_raise(ePKCS7Error, NULL);
+ }
+ if(!(out = PKCS7_dataInit(pkcs7, NULL))) goto err;
+ for(;;){
+ if((len = BIO_read(in, buf, sizeof(buf))) <= 0)
+ break;
+ if(BIO_write(out, buf, len) != len)
+ goto err;
+ }
+ if(!PKCS7_dataFinal(pkcs7, out)) goto err;
+ ossl_pkcs7_set_data(self, Qnil);
+
+ err:
+ BIO_free(out);
+ BIO_free(in);
+ if(ERR_peek_error()){
+ ossl_raise(ePKCS7Error, NULL);
+ }
+
+ 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;
+
+ GetPKCS7(self, pkcs7);
+ if (!(out = BIO_new(BIO_s_mem()))) {
+ ossl_raise(ePKCS7Error, NULL);
+ }
+ if (!PEM_write_bio_PKCS7(out, pkcs7)) {
+ BIO_free(out);
+ ossl_raise(ePKCS7Error, NULL);
+ }
+ str = ossl_membio2str(out);
+
+ return str;
+}
+
+/*
+ * SIGNER INFO
+ */
+static VALUE
+ossl_pkcs7si_alloc(VALUE klass)
+{
+ PKCS7_SIGNER_INFO *p7si;
+ VALUE obj;
+
+ if (!(p7si = PKCS7_SIGNER_INFO_new())) {
+ ossl_raise(ePKCS7Error, NULL);
+ }
+ WrapPKCS7si(klass, obj, p7si);
+
+ return obj;
+}
+
+static VALUE
+ossl_pkcs7si_initialize(VALUE self, VALUE cert, VALUE key, VALUE digest)
+{
+ PKCS7_SIGNER_INFO *p7si;
+ EVP_PKEY *pkey;
+ X509 *x509;
+ const EVP_MD *md;
+
+ pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */
+ x509 = GetX509CertPtr(cert); /* NO NEED TO DUP */
+ md = GetDigestPtr(digest);
+ GetPKCS7si(self, p7si);
+ if (!(PKCS7_SIGNER_INFO_set(p7si, x509, pkey, (EVP_MD*)md))) {
+ ossl_raise(ePKCS7Error, NULL);
+ }
+
+ return self;
+}
+
+static VALUE
+ossl_pkcs7si_get_issuer(VALUE self)
+{
+ PKCS7_SIGNER_INFO *p7si;
+
+ GetPKCS7si(self, p7si);
+
+ return ossl_x509name_new(p7si->issuer_and_serial->issuer);
+}
+
+static VALUE
+ossl_pkcs7si_get_serial(VALUE self)
+{
+ PKCS7_SIGNER_INFO *p7si;
+
+ GetPKCS7si(self, p7si);
+
+ return asn1integer_to_num(p7si->issuer_and_serial->serial);
+}
+
+static VALUE
+ossl_pkcs7si_get_signed_time(VALUE self)
+{
+ PKCS7_SIGNER_INFO *p7si;
+ ASN1_TYPE *asn1obj;
+
+ GetPKCS7si(self, p7si);
+
+ if (!(asn1obj = PKCS7_get_signed_attribute(p7si, NID_pkcs9_signingTime))) {
+ ossl_raise(ePKCS7Error, NULL);
+ }
+ if (asn1obj->type == V_ASN1_UTCTIME) {
+ return asn1time_to_time(asn1obj->value.utctime);
+ }
+ /*
+ * OR
+ * ossl_raise(ePKCS7Error, "...");
+ * ?
+ */
+
+ return Qnil;
+}
+
+/*
+ * RECIPIENT INFO
+ */
+static VALUE
+ossl_pkcs7ri_alloc(VALUE klass)
+{
+ PKCS7_RECIP_INFO *p7ri;
+ VALUE obj;
+
+ if (!(p7ri = PKCS7_RECIP_INFO_new())) {
+ ossl_raise(ePKCS7Error, NULL);
+ }
+ WrapPKCS7ri(klass, obj, p7ri);
+
+ return obj;
+}
+
+static VALUE
+ossl_pkcs7ri_initialize(VALUE self, VALUE cert)
+{
+ PKCS7_RECIP_INFO *p7ri;
+ X509 *x509;
+
+ x509 = GetX509CertPtr(cert); /* NO NEED TO DUP */
+ GetPKCS7ri(self, p7ri);
+ if (!PKCS7_RECIP_INFO_set(p7ri, x509)) {
+ ossl_raise(ePKCS7Error, NULL);
+ }
+
+ return self;
+}
+
+static VALUE
+ossl_pkcs7ri_get_issuer(VALUE self)
+{
+ PKCS7_RECIP_INFO *p7ri;
+
+ GetPKCS7ri(self, p7ri);
+
+ return ossl_x509name_new(p7ri->issuer_and_serial->issuer);
+}
+
+static VALUE
+ossl_pkcs7ri_get_serial(VALUE self)
+{
+ PKCS7_RECIP_INFO *p7ri;
+
+ GetPKCS7ri(self, p7ri);
+
+ return asn1integer_to_num(p7ri->issuer_and_serial->serial);
+}
+
+static VALUE
+ossl_pkcs7ri_get_enc_key(VALUE self)
+{
+ PKCS7_RECIP_INFO *p7ri;
+
+ GetPKCS7ri(self, p7ri);
+
+ return asn1str_to_str(p7ri->enc_key);
+}
+
+/*
+ * INIT
+ */
+void
+Init_ossl_pkcs7()
+{
+ mPKCS7 = rb_define_module_under(mOSSL, "PKCS7");
+
+ ePKCS7Error = rb_define_class_under(mPKCS7, "PKCS7Error", eOSSLError);
+
+ cPKCS7 = rb_define_class_under(mPKCS7, "PKCS7", rb_cObject);
+ rb_define_singleton_method(mPKCS7, "read_smime", ossl_pkcs7_s_read_smime, 1);
+ rb_define_singleton_method(mPKCS7, "write_smime", ossl_pkcs7_s_write_smime, -1);
+ rb_define_singleton_method(mPKCS7, "sign", ossl_pkcs7_s_sign, -1);
+ rb_define_singleton_method(mPKCS7, "encrypt", ossl_pkcs7_s_encrypt, -1);
+ rb_attr(cPKCS7, rb_intern("data"), 1, 0, Qfalse);
+ rb_attr(cPKCS7, rb_intern("error_string"), 1, 1, Qfalse);
+ rb_define_alloc_func(cPKCS7, ossl_pkcs7_alloc);
+ rb_define_copy_func(cPKCS7, ossl_pkcs7_copy);
+ rb_define_method(cPKCS7, "initialize", ossl_pkcs7_initialize, -1);
+ rb_define_method(cPKCS7, "type=", ossl_pkcs7_set_type, 1);
+ rb_define_method(cPKCS7, "type", ossl_pkcs7_get_type, 0);
+ rb_define_method(cPKCS7, "detached=", ossl_pkcs7_set_detached, 1);
+ rb_define_method(cPKCS7, "detached", ossl_pkcs7_get_detached, 0);
+ rb_define_method(cPKCS7, "detached?", ossl_pkcs7_detached_p, 0);
+ rb_define_method(cPKCS7, "cipher=", ossl_pkcs7_set_cipher, 1);
+ rb_define_method(cPKCS7, "add_signer", ossl_pkcs7_add_signer, 1);
+ rb_define_method(cPKCS7, "signers", ossl_pkcs7_get_signer, 0);
+ rb_define_method(cPKCS7, "add_recipient", ossl_pkcs7_add_recipient, 1);
+ rb_define_method(cPKCS7, "recipients", ossl_pkcs7_get_recipient, 0);
+ rb_define_method(cPKCS7, "add_certificate", ossl_pkcs7_add_certificate, 1);
+ rb_define_method(cPKCS7, "certificates=", ossl_pkcs7_set_certificates, 1);
+ rb_define_method(cPKCS7, "certificates", ossl_pkcs7_get_certificates, 0);
+ rb_define_method(cPKCS7, "add_crl", ossl_pkcs7_add_crl, 1);
+ rb_define_method(cPKCS7, "crls=", ossl_pkcs7_set_crls, 1);
+ rb_define_method(cPKCS7, "crls", ossl_pkcs7_get_crls, 0);
+ rb_define_method(cPKCS7, "add_data", ossl_pkcs7_add_data, 1);
+ rb_define_alias(cPKCS7, "data=", "add_data");
+ rb_define_method(cPKCS7, "verify", ossl_pkcs7_verify, -1);
+ 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, "SignerInfo", rb_cObject);
+ rb_define_const(mPKCS7, "Signer", cPKCS7Signer);
+ rb_define_alloc_func(cPKCS7Signer, ossl_pkcs7si_alloc);
+ rb_define_method(cPKCS7Signer, "initialize", ossl_pkcs7si_initialize,3);
+ rb_define_method(cPKCS7Signer, "issuer", ossl_pkcs7si_get_issuer, 0);
+ rb_define_alias(cPKCS7Signer, "name", "issuer");
+ rb_define_method(cPKCS7Signer, "serial", ossl_pkcs7si_get_serial,0);
+ rb_define_method(cPKCS7Signer,"signed_time",ossl_pkcs7si_get_signed_time,0);
+
+ cPKCS7Recipient = rb_define_class_under(mPKCS7,"RecipientInfo",rb_cObject);
+ rb_define_alloc_func(cPKCS7Recipient, ossl_pkcs7ri_alloc);
+ rb_define_method(cPKCS7Recipient, "initialize", ossl_pkcs7ri_initialize,1);
+ rb_define_method(cPKCS7Recipient, "issuer", ossl_pkcs7ri_get_issuer,0);
+ rb_define_method(cPKCS7Recipient, "serial", ossl_pkcs7ri_get_serial,0);
+ rb_define_method(cPKCS7Recipient, "enc_key", ossl_pkcs7ri_get_enc_key,0);
+
+#define DefPKCS7Const(x) rb_define_const(mPKCS7, #x, INT2NUM(PKCS7_##x))
+
+ DefPKCS7Const(TEXT);
+ DefPKCS7Const(NOCERTS);
+ DefPKCS7Const(NOSIGS);
+ DefPKCS7Const(NOCHAIN);
+ DefPKCS7Const(NOINTERN);
+ DefPKCS7Const(NOVERIFY);
+ DefPKCS7Const(DETACHED);
+ DefPKCS7Const(BINARY);
+ DefPKCS7Const(NOATTR);
+ DefPKCS7Const(NOSMIMECAP);
+}
diff --git a/ruby_1_8_5/ext/openssl/ossl_pkcs7.h b/ruby_1_8_5/ext/openssl/ossl_pkcs7.h
new file mode 100644
index 0000000000..fdf0d9fb34
--- /dev/null
+++ b/ruby_1_8_5/ext/openssl/ossl_pkcs7.h
@@ -0,0 +1,23 @@
+/*
+ * $Id: ossl_pkcs7.h,v 1.1.2.1 2005/09/10 01:17:00 gotoyuzo Exp $
+ * '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_PKCS7_H_)
+#define _OSSL_PKCS7_H_
+
+extern VALUE mPKCS7;
+extern VALUE cPKCS7;
+extern VALUE cPKCS7Signer;
+extern VALUE cPKCS7Recipient;
+extern VALUE ePKCS7Error;
+
+void Init_ossl_pkcs7(void);
+
+#endif /* _OSSL_PKCS7_H_ */
+
diff --git a/ruby_1_8_5/ext/openssl/ossl_pkey.c b/ruby_1_8_5/ext/openssl/ossl_pkey.c
new file mode 100644
index 0000000000..5a061597f6
--- /dev/null
+++ b/ruby_1_8_5/ext/openssl/ossl_pkey.c
@@ -0,0 +1,232 @@
+/*
+ * $Id: ossl_pkey.c,v 1.4.2.2 2005/04/08 09:26:54 gotoyuzo Exp $
+ * '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'.)
+ */
+#include "ossl.h"
+
+/*
+ * Classes
+ */
+VALUE mPKey;
+VALUE cPKey;
+VALUE ePKeyError;
+ID id_private_q;
+
+/*
+ * callback for generating keys
+ */
+void
+ossl_generate_cb(int p, int n, void *arg)
+{
+ VALUE ary;
+
+ ary = rb_ary_new2(2);
+ rb_ary_store(ary, 0, INT2NUM(p));
+ rb_ary_store(ary, 1, INT2NUM(n));
+
+ rb_yield(ary);
+}
+
+/*
+ * Public
+ */
+VALUE
+ossl_pkey_new(EVP_PKEY *pkey)
+{
+ if (!pkey) {
+ ossl_raise(ePKeyError, "Cannot make new key from NULL.");
+ }
+ switch (EVP_PKEY_type(pkey->type)) {
+#if !defined(OPENSSL_NO_RSA)
+ case EVP_PKEY_RSA:
+ return ossl_rsa_new(pkey);
+#endif
+#if !defined(OPENSSL_NO_DSA)
+ case EVP_PKEY_DSA:
+ return ossl_dsa_new(pkey);
+#endif
+#if !defined(OPENSSL_NO_DH)
+ case EVP_PKEY_DH:
+ return ossl_dh_new(pkey);
+#endif
+ default:
+ ossl_raise(ePKeyError, "unsupported key type");
+ }
+ return Qnil; /* not reached */
+}
+
+VALUE
+ossl_pkey_new_from_file(VALUE filename)
+{
+ FILE *fp;
+ EVP_PKEY *pkey;
+
+ SafeStringValue(filename);
+ if (!(fp = fopen(RSTRING(filename)->ptr, "r"))) {
+ ossl_raise(ePKeyError, "%s", strerror(errno));
+ }
+
+ pkey = PEM_read_PrivateKey(fp, NULL, ossl_pem_passwd_cb, NULL);
+ fclose(fp);
+ if (!pkey) {
+ ossl_raise(ePKeyError, NULL);
+ }
+
+ return ossl_pkey_new(pkey);
+}
+
+EVP_PKEY *
+GetPKeyPtr(VALUE obj)
+{
+ EVP_PKEY *pkey;
+
+ SafeGetPKey(obj, pkey);
+
+ return pkey;
+}
+
+EVP_PKEY *
+GetPrivPKeyPtr(VALUE obj)
+{
+ EVP_PKEY *pkey;
+
+ if (rb_funcall(obj, id_private_q, 0, NULL) != Qtrue) {
+ ossl_raise(rb_eArgError, "Private key is needed.");
+ }
+ SafeGetPKey(obj, pkey);
+
+ return pkey;
+}
+
+EVP_PKEY *
+DupPKeyPtr(VALUE obj)
+{
+ EVP_PKEY *pkey;
+
+ SafeGetPKey(obj, pkey);
+ CRYPTO_add(&pkey->references, 1, CRYPTO_LOCK_EVP_PKEY);
+
+ return pkey;
+}
+
+EVP_PKEY *
+DupPrivPKeyPtr(VALUE obj)
+{
+ EVP_PKEY *pkey;
+
+ if (rb_funcall(obj, id_private_q, 0, NULL) != Qtrue) {
+ ossl_raise(rb_eArgError, "Private key is needed.");
+ }
+ SafeGetPKey(obj, pkey);
+ CRYPTO_add(&pkey->references, 1, CRYPTO_LOCK_EVP_PKEY);
+
+ return pkey;
+}
+
+/*
+ * Private
+ */
+static VALUE
+ossl_pkey_alloc(VALUE klass)
+{
+ EVP_PKEY *pkey;
+ VALUE obj;
+
+ if (!(pkey = EVP_PKEY_new())) {
+ ossl_raise(ePKeyError, NULL);
+ }
+ WrapPKey(klass, obj, pkey);
+
+ return obj;
+}
+
+static VALUE
+ossl_pkey_initialize(VALUE self)
+{
+ if (rb_obj_is_instance_of(self, cPKey)) {
+ ossl_raise(rb_eNotImpError, "OpenSSL::PKey::PKey is an abstract class.");
+ }
+ return self;
+}
+
+static VALUE
+ossl_pkey_sign(VALUE self, VALUE digest, VALUE data)
+{
+ EVP_PKEY *pkey;
+ EVP_MD_CTX ctx;
+ int buf_len;
+ VALUE str;
+
+ if (rb_funcall(self, id_private_q, 0, NULL) != Qtrue) {
+ ossl_raise(rb_eArgError, "Private key is needed.");
+ }
+ GetPKey(self, pkey);
+ EVP_SignInit(&ctx, GetDigestPtr(digest));
+ StringValue(data);
+ EVP_SignUpdate(&ctx, RSTRING(data)->ptr, RSTRING(data)->len);
+ str = rb_str_new(0, EVP_PKEY_size(pkey)+16);
+ if (!EVP_SignFinal(&ctx, RSTRING(str)->ptr, &buf_len, pkey))
+ ossl_raise(ePKeyError, NULL);
+ assert(buf_len <= RSTRING(str)->len);
+ RSTRING(str)->len = buf_len;
+ RSTRING(str)->ptr[buf_len] = 0;
+
+ return str;
+}
+
+static VALUE
+ossl_pkey_verify(VALUE self, VALUE digest, VALUE sig, VALUE data)
+{
+ EVP_PKEY *pkey;
+ EVP_MD_CTX ctx;
+
+ GetPKey(self, pkey);
+ EVP_VerifyInit(&ctx, GetDigestPtr(digest));
+ StringValue(sig);
+ StringValue(data);
+ EVP_VerifyUpdate(&ctx, RSTRING(data)->ptr, RSTRING(data)->len);
+ switch (EVP_VerifyFinal(&ctx, RSTRING(sig)->ptr, RSTRING(sig)->len, pkey)) {
+ case 0:
+ return Qfalse;
+ case 1:
+ return Qtrue;
+ default:
+ ossl_raise(ePKeyError, NULL);
+ }
+ return Qnil; /* dummy */
+}
+
+/*
+ * INIT
+ */
+void
+Init_ossl_pkey()
+{
+ mPKey = rb_define_module_under(mOSSL, "PKey");
+
+ ePKeyError = rb_define_class_under(mPKey, "PKeyError", eOSSLError);
+
+ cPKey = rb_define_class_under(mPKey, "PKey", rb_cObject);
+
+ rb_define_alloc_func(cPKey, ossl_pkey_alloc);
+ rb_define_method(cPKey, "initialize", ossl_pkey_initialize, 0);
+
+ rb_define_method(cPKey, "sign", ossl_pkey_sign, 2);
+ rb_define_method(cPKey, "verify", ossl_pkey_verify, 3);
+
+ id_private_q = rb_intern("private?");
+
+ /*
+ * INIT rsa, dsa
+ */
+ Init_ossl_rsa();
+ Init_ossl_dsa();
+ Init_ossl_dh();
+}
+
diff --git a/ruby_1_8_5/ext/openssl/ossl_pkey.h b/ruby_1_8_5/ext/openssl/ossl_pkey.h
new file mode 100644
index 0000000000..224f0f4634
--- /dev/null
+++ b/ruby_1_8_5/ext/openssl/ossl_pkey.h
@@ -0,0 +1,120 @@
+/*
+ * $Id: ossl_pkey.h,v 1.2.2.2 2005/09/18 22:56:11 gotoyuzo Exp $
+ * 'OpenSSL for Ruby' project
+ * Copyright (C) 2001 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_PKEY_H_)
+#define _OSSL_PKEY_H_
+
+extern VALUE mPKey;
+extern VALUE cPKey;
+extern VALUE ePKeyError;
+extern ID id_private_q;
+
+#define OSSL_PKEY_SET_PRIVATE(obj) rb_iv_set((obj), "private", Qtrue)
+#define OSSL_PKEY_SET_PUBLIC(obj) rb_iv_set((obj), "private", Qfalse)
+#define OSSL_PKEY_IS_PRIVATE(obj) (rb_iv_get((obj), "private") == Qtrue)
+
+#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); \
+ OSSL_PKEY_SET_PUBLIC(obj); \
+} 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)
+
+void ossl_generate_cb(int, int, void *);
+
+VALUE ossl_pkey_new(EVP_PKEY *);
+VALUE ossl_pkey_new_from_file(VALUE);
+EVP_PKEY *GetPKeyPtr(VALUE);
+EVP_PKEY *DupPKeyPtr(VALUE);
+EVP_PKEY *GetPrivPKeyPtr(VALUE);
+EVP_PKEY *DupPrivPKeyPtr(VALUE);
+void Init_ossl_pkey(void);
+
+/*
+ * RSA
+ */
+extern VALUE cRSA;
+extern VALUE eRSAError;
+
+VALUE ossl_rsa_new(EVP_PKEY *);
+void Init_ossl_rsa(void);
+
+/*
+ * DSA
+ */
+extern VALUE cDSA;
+extern VALUE eDSAError;
+
+VALUE ossl_dsa_new(EVP_PKEY *);
+void Init_ossl_dsa(void);
+
+/*
+ * DH
+ */
+extern VALUE cDH;
+extern VALUE eDHError;
+extern DH *OSSL_DEFAULT_DH_512;
+extern DH *OSSL_DEFAULT_DH_1024;
+
+VALUE ossl_dh_new(EVP_PKEY *);
+void Init_ossl_dh(void);
+
+#define OSSL_PKEY_BN(keytype, name) \
+static VALUE ossl_##keytype##_get_##name(VALUE self) \
+{ \
+ EVP_PKEY *pkey; \
+ BIGNUM *bn; \
+ \
+ GetPKey(self, pkey); \
+ bn = pkey->pkey.keytype->name; \
+ if (bn == NULL) \
+ return Qnil; \
+ return ossl_bn_new(bn); \
+} \
+static VALUE ossl_##keytype##_set_##name(VALUE self, VALUE bignum) \
+{ \
+ EVP_PKEY *pkey; \
+ BIGNUM *bn; \
+ \
+ GetPKey(self, pkey); \
+ if (NIL_P(bignum)) { \
+ BN_clear_free(pkey->pkey.keytype->name); \
+ pkey->pkey.keytype->name = NULL; \
+ return Qnil; \
+ } \
+ \
+ bn = GetBNPtr(bignum); \
+ if (pkey->pkey.keytype->name == NULL) \
+ pkey->pkey.keytype->name = BN_new(); \
+ if (pkey->pkey.keytype->name == NULL) \
+ ossl_raise(eBNError, NULL); \
+ if (BN_copy(pkey->pkey.keytype->name, bn) == NULL) \
+ ossl_raise(eBNError, NULL); \
+ return bignum; \
+}
+
+#define DEF_OSSL_PKEY_BN(class, keytype, name) \
+do { \
+ rb_define_method(class, #name, ossl_##keytype##_get_##name, 0); \
+ rb_define_method(class, #name "=", ossl_##keytype##_set_##name, 1);\
+} while (0)
+
+#endif /* _OSSL_PKEY_H_ */
diff --git a/ruby_1_8_5/ext/openssl/ossl_pkey_dh.c b/ruby_1_8_5/ext/openssl/ossl_pkey_dh.c
new file mode 100644
index 0000000000..79692f2f47
--- /dev/null
+++ b/ruby_1_8_5/ext/openssl/ossl_pkey_dh.c
@@ -0,0 +1,458 @@
+/*
+ * $Id: ossl_pkey_dh.c,v 1.4.2.3 2005/04/08 09:26:54 gotoyuzo Exp $
+ * '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(OPENSSL_NO_DH)
+
+#include "ossl.h"
+
+#define GetPKeyDH(obj, pkey) do { \
+ GetPKey(obj, pkey); \
+ if (EVP_PKEY_type(pkey->type) != EVP_PKEY_DH) { /* PARANOIA? */ \
+ ossl_raise(rb_eRuntimeError, "THIS IS NOT A DH!") ; \
+ } \
+} while (0)
+
+#define DH_HAS_PRIVATE(dh) ((dh)->priv_key)
+
+#ifdef OSSL_ENGINE_ENABLED
+# define DH_PRIVATE(dh) (DH_HAS_PRIVATE(dh) || (dh)->engine)
+#else
+# define DH_PRIVATE(dh) DH_HAS_PRIVATE(dh)
+#endif
+
+
+/*
+ * Classes
+ */
+VALUE cDH;
+VALUE eDHError;
+
+/*
+ * Public
+ */
+static VALUE
+dh_instance(VALUE klass, DH *dh)
+{
+ EVP_PKEY *pkey;
+ VALUE obj;
+
+ 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 obj;
+}
+
+VALUE
+ossl_dh_new(EVP_PKEY *pkey)
+{
+ VALUE obj;
+
+ if (!pkey) {
+ obj = dh_instance(cDH, DH_new());
+ } else {
+ if (EVP_PKEY_type(pkey->type) != EVP_PKEY_DH) {
+ ossl_raise(rb_eTypeError, "Not a DH key!");
+ }
+ WrapPKey(cDH, obj, pkey);
+ }
+ if (obj == Qfalse) {
+ ossl_raise(eDHError, NULL);
+ }
+
+ return obj;
+}
+
+/*
+ * Private
+ */
+static DH *
+dh_generate(int size, int gen)
+{
+ DH *dh;
+
+ dh = DH_generate_parameters(size, gen,
+ rb_block_given_p() ? ossl_generate_cb : NULL,
+ NULL);
+ if (!dh) return 0;
+
+ if (!DH_generate_key(dh)) {
+ DH_free(dh);
+ 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;
+
+ 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, NULL);
+ }
+
+ return obj;
+}
+
+static VALUE
+ossl_dh_initialize(int argc, VALUE *argv, VALUE self)
+{
+ EVP_PKEY *pkey;
+ DH *dh;
+ int g = 2;
+ BIO *in;
+ VALUE arg, gen;
+
+ GetPKey(self, pkey);
+ if(rb_scan_args(argc, argv, "02", &arg, &gen) == 0) {
+ dh = DH_new();
+ }
+ else if (FIXNUM_P(arg)) {
+ if (!NIL_P(gen)) {
+ g = FIX2INT(gen);
+ }
+ if (!(dh = dh_generate(FIX2INT(arg), g))) {
+ 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);
+ ossl_raise(eDHError, NULL);
+ }
+ return self;
+}
+
+static VALUE
+ossl_dh_is_public(VALUE self)
+{
+ EVP_PKEY *pkey;
+
+ GetPKeyDH(self, pkey);
+ /*
+ * Do we need to check dhp->dh->public_pkey?
+ * return Qtrue;
+ */
+ return (pkey->pkey.dh->pub_key) ? Qtrue : Qfalse;
+}
+
+static VALUE
+ossl_dh_is_private(VALUE self)
+{
+ EVP_PKEY *pkey;
+
+ GetPKeyDH(self, pkey);
+
+ return (DH_PRIVATE(pkey->pkey.dh)) ? Qtrue : Qfalse;
+}
+
+static VALUE
+ossl_dh_export(VALUE self)
+{
+ EVP_PKEY *pkey;
+ BIO *out;
+ VALUE str;
+
+ GetPKeyDH(self, pkey);
+ if (!(out = BIO_new(BIO_s_mem()))) {
+ ossl_raise(eDHError, NULL);
+ }
+ if (!PEM_write_bio_DHparams(out, pkey->pkey.dh)) {
+ BIO_free(out);
+ ossl_raise(eDHError, NULL);
+ }
+ str = ossl_membio2str(out);
+
+ return str;
+}
+
+static VALUE
+ossl_dh_to_der(VALUE self)
+{
+ EVP_PKEY *pkey;
+ unsigned char *p;
+ long len;
+ VALUE str;
+
+ GetPKeyDH(self, pkey);
+ if((len = i2d_DHparams(pkey->pkey.dh, NULL)) <= 0)
+ ossl_raise(eDHError, NULL);
+ str = rb_str_new(0, len);
+ p = RSTRING(str)->ptr;
+ if(i2d_DHparams(pkey->pkey.dh, &p) < 0)
+ ossl_raise(eDHError, NULL);
+ ossl_str_adjust(str, p);
+
+ return str;
+}
+
+/*
+ * Stores all parameters of key to the hash
+ * INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!!
+ * Don't use :-)) (I's up to you)
+ */
+static VALUE
+ossl_dh_get_params(VALUE self)
+{
+ EVP_PKEY *pkey;
+ VALUE hash;
+
+ GetPKeyDH(self, pkey);
+
+ hash = rb_hash_new();
+
+ rb_hash_aset(hash, rb_str_new2("p"), ossl_bn_new(pkey->pkey.dh->p));
+ rb_hash_aset(hash, rb_str_new2("g"), ossl_bn_new(pkey->pkey.dh->g));
+ rb_hash_aset(hash, rb_str_new2("pub_key"), ossl_bn_new(pkey->pkey.dh->pub_key));
+ rb_hash_aset(hash, rb_str_new2("priv_key"), ossl_bn_new(pkey->pkey.dh->priv_key));
+
+ return hash;
+}
+
+/*
+ * Prints all parameters of key to buffer
+ * INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!!
+ * Don't use :-)) (I's up to you)
+ */
+static VALUE
+ossl_dh_to_text(VALUE self)
+{
+ EVP_PKEY *pkey;
+ BIO *out;
+ VALUE str;
+
+ GetPKeyDH(self, pkey);
+ if (!(out = BIO_new(BIO_s_mem()))) {
+ ossl_raise(eDHError, NULL);
+ }
+ if (!DHparams_print(out, pkey->pkey.dh)) {
+ BIO_free(out);
+ ossl_raise(eDHError, NULL);
+ }
+ str = ossl_membio2str(out);
+
+ return str;
+}
+
+/*
+ * Makes new instance DH PUBLIC_KEY from PRIVATE_KEY
+ */
+static VALUE
+ossl_dh_to_public_key(VALUE self)
+{
+ EVP_PKEY *pkey;
+ DH *dh;
+ VALUE obj;
+
+ GetPKeyDH(self, pkey);
+ 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, NULL);
+ }
+
+ return obj;
+}
+
+static VALUE
+ossl_dh_check_params(VALUE self)
+{
+ DH *dh;
+ EVP_PKEY *pkey;
+ int codes;
+
+ GetPKeyDH(self, pkey);
+ dh = pkey->pkey.dh;
+
+ if (!DH_check(dh, &codes)) {
+ return Qfalse;
+ }
+
+ return codes == 0 ? Qtrue : Qfalse;
+}
+
+static VALUE
+ossl_dh_generate_key(VALUE self)
+{
+ DH *dh;
+ EVP_PKEY *pkey;
+
+ GetPKeyDH(self, pkey);
+ dh = pkey->pkey.dh;
+
+ if (!DH_generate_key(dh))
+ ossl_raise(eDHError, "Failed to generate key");
+ return self;
+}
+
+static VALUE
+ossl_dh_compute_key(VALUE self, VALUE pub)
+{
+ DH *dh;
+ EVP_PKEY *pkey;
+ BIGNUM *pub_key;
+ VALUE str;
+ int len;
+
+ GetPKeyDH(self, pkey);
+ dh = pkey->pkey.dh;
+ pub_key = GetBNPtr(pub);
+ len = DH_size(dh);
+ str = rb_str_new(0, len);
+ if ((len = DH_compute_key(RSTRING(str)->ptr, pub_key, dh)) < 0) {
+ ossl_raise(eDHError, NULL);
+ }
+ RSTRING(str)->len = len;
+ RSTRING(str)->ptr[len] = 0;
+
+ return str;
+}
+
+OSSL_PKEY_BN(dh, p);
+OSSL_PKEY_BN(dh, g);
+OSSL_PKEY_BN(dh, pub_key);
+OSSL_PKEY_BN(dh, priv_key);
+
+/*
+ * -----BEGIN DH PARAMETERS-----
+ * MEYCQQD0zXHljRg/mJ9PYLACLv58Cd8VxBxxY7oEuCeURMiTqEhMym16rhhKgZG2
+ * zk2O9uUIBIxSj+NKMURHGaFKyIvLAgEC
+ * -----END DH PARAMETERS-----
+ */
+static unsigned char DEFAULT_DH_512_PRIM[] = {
+ 0xf4, 0xcd, 0x71, 0xe5, 0x8d, 0x18, 0x3f, 0x98,
+ 0x9f, 0x4f, 0x60, 0xb0, 0x02, 0x2e, 0xfe, 0x7c,
+ 0x09, 0xdf, 0x15, 0xc4, 0x1c, 0x71, 0x63, 0xba,
+ 0x04, 0xb8, 0x27, 0x94, 0x44, 0xc8, 0x93, 0xa8,
+ 0x48, 0x4c, 0xca, 0x6d, 0x7a, 0xae, 0x18, 0x4a,
+ 0x81, 0x91, 0xb6, 0xce, 0x4d, 0x8e, 0xf6, 0xe5,
+ 0x08, 0x04, 0x8c, 0x52, 0x8f, 0xe3, 0x4a, 0x31,
+ 0x44, 0x47, 0x19, 0xa1, 0x4a, 0xc8, 0x8b, 0xcb,
+};
+static unsigned char DEFAULT_DH_512_GEN[] = { 0x02 };
+DH *OSSL_DEFAULT_DH_512 = NULL;
+
+/*
+ * -----BEGIN DH PARAMETERS-----
+ * MIGHAoGBAJ0lOVy0VIr/JebWn0zDwY2h+rqITFOpdNr6ugsgvkDXuucdcChhYExJ
+ * AV/ZD2AWPbrTqV76mGRgJg4EddgT1zG0jq3rnFdMj2XzkBYx3BVvfR0Arnby0RHR
+ * T4h7KZ/2zmjvV+eF8kBUHBJAojUlzxKj4QeO2x20FP9X5xmNUXeDAgEC
+ * -----END DH PARAMETERS-----
+ */
+static unsigned char DEFAULT_DH_1024_PRIM[] = {
+ 0x9d, 0x25, 0x39, 0x5c, 0xb4, 0x54, 0x8a, 0xff,
+ 0x25, 0xe6, 0xd6, 0x9f, 0x4c, 0xc3, 0xc1, 0x8d,
+ 0xa1, 0xfa, 0xba, 0x88, 0x4c, 0x53, 0xa9, 0x74,
+ 0xda, 0xfa, 0xba, 0x0b, 0x20, 0xbe, 0x40, 0xd7,
+ 0xba, 0xe7, 0x1d, 0x70, 0x28, 0x61, 0x60, 0x4c,
+ 0x49, 0x01, 0x5f, 0xd9, 0x0f, 0x60, 0x16, 0x3d,
+ 0xba, 0xd3, 0xa9, 0x5e, 0xfa, 0x98, 0x64, 0x60,
+ 0x26, 0x0e, 0x04, 0x75, 0xd8, 0x13, 0xd7, 0x31,
+ 0xb4, 0x8e, 0xad, 0xeb, 0x9c, 0x57, 0x4c, 0x8f,
+ 0x65, 0xf3, 0x90, 0x16, 0x31, 0xdc, 0x15, 0x6f,
+ 0x7d, 0x1d, 0x00, 0xae, 0x76, 0xf2, 0xd1, 0x11,
+ 0xd1, 0x4f, 0x88, 0x7b, 0x29, 0x9f, 0xf6, 0xce,
+ 0x68, 0xef, 0x57, 0xe7, 0x85, 0xf2, 0x40, 0x54,
+ 0x1c, 0x12, 0x40, 0xa2, 0x35, 0x25, 0xcf, 0x12,
+ 0xa3, 0xe1, 0x07, 0x8e, 0xdb, 0x1d, 0xb4, 0x14,
+ 0xff, 0x57, 0xe7, 0x19, 0x8d, 0x51, 0x77, 0x83
+};
+static unsigned char DEFAULT_DH_1024_GEN[] = { 0x02 };
+DH *OSSL_DEFAULT_DH_1024 = NULL;
+
+static DH*
+ossl_create_dh(unsigned char *p, size_t plen, unsigned char *g, size_t glen)
+{
+ DH *dh;
+
+ if ((dh = DH_new()) == NULL) ossl_raise(eDHError, NULL);
+ dh->p = BN_bin2bn(p, plen, NULL);
+ dh->g = BN_bin2bn(g, glen, NULL);
+ if (dh->p == NULL || dh->g == NULL){
+ DH_free(dh);
+ ossl_raise(eDHError, NULL);
+ }
+
+ return dh;
+}
+
+/*
+ * INIT
+ */
+void
+Init_ossl_dh()
+{
+ eDHError = rb_define_class_under(mPKey, "DHError", ePKeyError);
+ cDH = rb_define_class_under(mPKey, "DH", cPKey);
+ 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);
+ rb_define_method(cDH, "to_text", ossl_dh_to_text, 0);
+ rb_define_method(cDH, "export", ossl_dh_export, 0);
+ rb_define_alias(cDH, "to_pem", "export");
+ rb_define_alias(cDH, "to_s", "export");
+ rb_define_method(cDH, "to_der", ossl_dh_to_der, 0);
+ rb_define_method(cDH, "public_key", ossl_dh_to_public_key, 0);
+ rb_define_method(cDH, "params_ok?", ossl_dh_check_params, 0);
+ rb_define_method(cDH, "generate_key!", ossl_dh_generate_key, 0);
+ rb_define_method(cDH, "compute_key", ossl_dh_compute_key, 1);
+ DEF_OSSL_PKEY_BN(cDH, dh, p);
+ DEF_OSSL_PKEY_BN(cDH, dh, g);
+ DEF_OSSL_PKEY_BN(cDH, dh, pub_key);
+ DEF_OSSL_PKEY_BN(cDH, dh, priv_key);
+ rb_define_method(cDH, "params", ossl_dh_get_params, 0);
+
+ OSSL_DEFAULT_DH_512 = ossl_create_dh(
+ DEFAULT_DH_512_PRIM, sizeof(DEFAULT_DH_512_PRIM),
+ DEFAULT_DH_512_GEN, sizeof(DEFAULT_DH_512_GEN));
+ OSSL_DEFAULT_DH_1024 = ossl_create_dh(
+ DEFAULT_DH_1024_PRIM, sizeof(DEFAULT_DH_1024_PRIM),
+ DEFAULT_DH_1024_GEN, sizeof(DEFAULT_DH_1024_GEN));
+}
+
+#else /* defined NO_DH */
+# warning >>> OpenSSL is compiled without DH support <<<
+void
+Init_ossl_dh()
+{
+ rb_warning("OpenSSL is compiled without DH support");
+}
+#endif /* NO_DH */
+
diff --git a/ruby_1_8_5/ext/openssl/ossl_pkey_dsa.c b/ruby_1_8_5/ext/openssl/ossl_pkey_dsa.c
new file mode 100644
index 0000000000..2a6060fe77
--- /dev/null
+++ b/ruby_1_8_5/ext/openssl/ossl_pkey_dsa.c
@@ -0,0 +1,417 @@
+/*
+ * $Id: ossl_pkey_dsa.c,v 1.5.2.3 2005/09/18 22:56:11 gotoyuzo Exp $
+ * '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(OPENSSL_NO_DSA)
+
+#include "ossl.h"
+
+#define GetPKeyDSA(obj, pkey) do { \
+ GetPKey(obj, pkey); \
+ if (EVP_PKEY_type(pkey->type) != EVP_PKEY_DSA) { /* PARANOIA? */ \
+ ossl_raise(rb_eRuntimeError, "THIS IS NOT A DSA!"); \
+ } \
+} while (0)
+
+#define DSA_HAS_PRIVATE(dsa) ((dsa)->priv_key)
+#define DSA_PRIVATE(obj,dsa) (DSA_HAS_PRIVATE(dsa)||OSSL_PKEY_IS_PRIVATE(obj))
+
+/*
+ * Classes
+ */
+VALUE cDSA;
+VALUE eDSAError;
+
+/*
+ * Public
+ */
+static VALUE
+dsa_instance(VALUE klass, DSA *dsa)
+{
+ EVP_PKEY *pkey;
+ VALUE obj;
+
+ if (!dsa) {
+ return Qfalse;
+ }
+ if (!(pkey = EVP_PKEY_new())) {
+ return Qfalse;
+ }
+ if (!EVP_PKEY_assign_DSA(pkey, dsa)) {
+ EVP_PKEY_free(pkey);
+ return Qfalse;
+ }
+ WrapPKey(klass, obj, pkey);
+
+ return obj;
+}
+
+VALUE
+ossl_dsa_new(EVP_PKEY *pkey)
+{
+ VALUE obj;
+
+ if (!pkey) {
+ obj = dsa_instance(cDSA, DSA_new());
+ } else {
+ if (EVP_PKEY_type(pkey->type) != EVP_PKEY_DSA) {
+ ossl_raise(rb_eTypeError, "Not a DSA key!");
+ }
+ WrapPKey(cDSA, obj, pkey);
+ }
+ if (obj == Qfalse) {
+ ossl_raise(eDSAError, NULL);
+ }
+
+ return obj;
+}
+
+/*
+ * Private
+ */
+static DSA *
+dsa_generate(int size)
+{
+ DSA *dsa;
+ unsigned char seed[20];
+ int seed_len = 20, counter;
+ unsigned long h;
+
+ if (!RAND_bytes(seed, seed_len)) {
+ return 0;
+ }
+ dsa = DSA_generate_parameters(size, seed, seed_len, &counter, &h,
+ rb_block_given_p() ? ossl_generate_cb : NULL,
+ NULL);
+ if(!dsa) 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, NULL);
+ }
+
+ return obj;
+}
+
+static VALUE
+ossl_dsa_initialize(int argc, VALUE *argv, VALUE self)
+{
+ EVP_PKEY *pkey;
+ DSA *dsa;
+ BIO *in;
+ char *passwd = NULL;
+ VALUE arg, pass;
+
+ GetPKey(self, pkey);
+ if(rb_scan_args(argc, argv, "02", &arg, &pass) == 0) {
+ dsa = DSA_new();
+ }
+ else if (FIXNUM_P(arg)) {
+ if (!(dsa = dsa_generate(FIX2INT(arg)))) {
+ 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);
+ 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_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);
+ ossl_raise(eDSAError, NULL);
+ }
+
+ return self;
+}
+
+static VALUE
+ossl_dsa_is_public(VALUE self)
+{
+ EVP_PKEY *pkey;
+
+ GetPKeyDSA(self, pkey);
+
+ /*
+ * Do we need to check dsap->dsa->public_pkey?
+ * return Qtrue;
+ */
+ return (pkey->pkey.dsa->pub_key) ? Qtrue : Qfalse;
+}
+
+static VALUE
+ossl_dsa_is_private(VALUE self)
+{
+ EVP_PKEY *pkey;
+
+ GetPKeyDSA(self, pkey);
+
+ return (DSA_PRIVATE(self, pkey->pkey.dsa)) ? Qtrue : Qfalse;
+}
+
+static VALUE
+ossl_dsa_export(int argc, VALUE *argv, VALUE self)
+{
+ EVP_PKEY *pkey;
+ BIO *out;
+ const EVP_CIPHER *ciph = NULL;
+ char *passwd = NULL;
+ VALUE cipher, pass, str;
+
+ GetPKeyDSA(self, pkey);
+ rb_scan_args(argc, argv, "02", &cipher, &pass);
+ if (!NIL_P(cipher)) {
+ ciph = GetCipherPtr(cipher);
+ if (!NIL_P(pass)) {
+ passwd = StringValuePtr(pass);
+ }
+ }
+ if (!(out = BIO_new(BIO_s_mem()))) {
+ ossl_raise(eDSAError, NULL);
+ }
+ if (DSA_HAS_PRIVATE(pkey->pkey.dsa)) {
+ if (!PEM_write_bio_DSAPrivateKey(out, pkey->pkey.dsa, ciph,
+ NULL, 0, ossl_pem_passwd_cb, passwd)){
+ BIO_free(out);
+ ossl_raise(eDSAError, NULL);
+ }
+ } else {
+ if (!PEM_write_bio_DSAPublicKey(out, pkey->pkey.dsa)) {
+ BIO_free(out);
+ ossl_raise(eDSAError, NULL);
+ }
+ }
+ str = ossl_membio2str(out);
+
+ return str;
+}
+
+static VALUE
+ossl_dsa_to_der(VALUE self)
+{
+ EVP_PKEY *pkey;
+ int (*i2d_func)_((DSA*, unsigned char**));
+ unsigned char *p;
+ long len;
+ VALUE str;
+
+ GetPKeyDSA(self, pkey);
+ if(DSA_HAS_PRIVATE(pkey->pkey.dsa))
+ i2d_func = (int(*)_((DSA*,unsigned char**)))i2d_DSAPrivateKey;
+ else
+ i2d_func = i2d_DSA_PUBKEY;
+ if((len = i2d_func(pkey->pkey.dsa, NULL)) <= 0)
+ ossl_raise(eDSAError, NULL);
+ str = rb_str_new(0, len);
+ p = RSTRING(str)->ptr;
+ if(i2d_func(pkey->pkey.dsa, &p) < 0)
+ ossl_raise(eDSAError, NULL);
+ ossl_str_adjust(str, p);
+
+ return str;
+}
+
+/*
+ * Stores all parameters of key to the hash
+ * INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!!
+ * Don't use :-)) (I's up to you)
+ */
+static VALUE
+ossl_dsa_get_params(VALUE self)
+{
+ EVP_PKEY *pkey;
+ VALUE hash;
+
+ GetPKeyDSA(self, pkey);
+
+ hash = rb_hash_new();
+
+ rb_hash_aset(hash, rb_str_new2("p"), ossl_bn_new(pkey->pkey.dsa->p));
+ rb_hash_aset(hash, rb_str_new2("q"), ossl_bn_new(pkey->pkey.dsa->q));
+ rb_hash_aset(hash, rb_str_new2("g"), ossl_bn_new(pkey->pkey.dsa->g));
+ rb_hash_aset(hash, rb_str_new2("pub_key"), ossl_bn_new(pkey->pkey.dsa->pub_key));
+ rb_hash_aset(hash, rb_str_new2("priv_key"), ossl_bn_new(pkey->pkey.dsa->priv_key));
+
+ return hash;
+}
+
+/*
+ * Prints all parameters of key to buffer
+ * INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!!
+ * Don't use :-)) (I's up to you)
+ */
+static VALUE
+ossl_dsa_to_text(VALUE self)
+{
+ EVP_PKEY *pkey;
+ BIO *out;
+ VALUE str;
+
+ GetPKeyDSA(self, pkey);
+ if (!(out = BIO_new(BIO_s_mem()))) {
+ ossl_raise(eDSAError, NULL);
+ }
+ if (!DSA_print(out, pkey->pkey.dsa, 0)) { /* offset = 0 */
+ BIO_free(out);
+ ossl_raise(eDSAError, NULL);
+ }
+ str = ossl_membio2str(out);
+
+ return str;
+}
+
+/*
+ * Makes new instance DSA PUBLIC_KEY from PRIVATE_KEY
+ */
+static VALUE
+ossl_dsa_to_public_key(VALUE self)
+{
+ EVP_PKEY *pkey;
+ DSA *dsa;
+ VALUE obj;
+
+ GetPKeyDSA(self, pkey);
+ /* err check performed by dsa_instance */
+ dsa = DSAPublicKey_dup(pkey->pkey.dsa);
+ obj = dsa_instance(CLASS_OF(self), dsa);
+ if (obj == Qfalse) {
+ DSA_free(dsa);
+ ossl_raise(eDSAError, NULL);
+ }
+ 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;
+ int buf_len;
+ VALUE str;
+
+ GetPKeyDSA(self, pkey);
+ StringValue(data);
+ if (!DSA_PRIVATE(self, pkey->pkey.dsa)) {
+ ossl_raise(eDSAError, "Private DSA key needed!");
+ }
+ 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) */
+ ossl_raise(eDSAError, NULL);
+ }
+ RSTRING(str)->len = buf_len;
+ RSTRING(str)->ptr[buf_len] = 0;
+
+ return str;
+}
+
+static VALUE
+ossl_dsa_verify(VALUE self, VALUE digest, VALUE sig)
+{
+ EVP_PKEY *pkey;
+ int ret;
+
+ GetPKeyDSA(self, pkey);
+ StringValue(digest);
+ StringValue(sig);
+ /* type is ignored (0) */
+ ret = DSA_verify(0, RSTRING(digest)->ptr, RSTRING(digest)->len,
+ RSTRING(sig)->ptr, RSTRING(sig)->len, pkey->pkey.dsa);
+ if (ret < 0) {
+ ossl_raise(eDSAError, NULL);
+ }
+ else if (ret == 1) {
+ return Qtrue;
+ }
+
+ return Qfalse;
+}
+
+OSSL_PKEY_BN(dsa, p);
+OSSL_PKEY_BN(dsa, q);
+OSSL_PKEY_BN(dsa, g);
+OSSL_PKEY_BN(dsa, pub_key);
+OSSL_PKEY_BN(dsa, priv_key);
+
+/*
+ * INIT
+ */
+void
+Init_ossl_dsa()
+{
+ eDSAError = rb_define_class_under(mPKey, "DSAError", ePKeyError);
+
+ cDSA = rb_define_class_under(mPKey, "DSA", cPKey);
+
+ rb_define_singleton_method(cDSA, "generate", ossl_dsa_s_generate, 1);
+ 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);
+ rb_define_method(cDSA, "to_text", ossl_dsa_to_text, 0);
+ rb_define_method(cDSA, "export", ossl_dsa_export, -1);
+ rb_define_alias(cDSA, "to_pem", "export");
+ rb_define_alias(cDSA, "to_s", "export");
+ rb_define_method(cDSA, "to_der", ossl_dsa_to_der, 0);
+ rb_define_method(cDSA, "public_key", ossl_dsa_to_public_key, 0);
+ rb_define_method(cDSA, "syssign", ossl_dsa_sign, 1);
+ rb_define_method(cDSA, "sysverify", ossl_dsa_verify, 2);
+
+ DEF_OSSL_PKEY_BN(cDSA, dsa, p);
+ DEF_OSSL_PKEY_BN(cDSA, dsa, q);
+ DEF_OSSL_PKEY_BN(cDSA, dsa, g);
+ DEF_OSSL_PKEY_BN(cDSA, dsa, pub_key);
+ DEF_OSSL_PKEY_BN(cDSA, dsa, priv_key);
+
+ rb_define_method(cDSA, "params", ossl_dsa_get_params, 0);
+}
+
+#else /* defined NO_DSA */
+# warning >>> OpenSSL is compiled without DSA support <<<
+
+void
+Init_ossl_dsa()
+{
+ rb_warning("OpenSSL is compiled without DSA support");
+}
+
+#endif /* NO_DSA */
diff --git a/ruby_1_8_5/ext/openssl/ossl_pkey_rsa.c b/ruby_1_8_5/ext/openssl/ossl_pkey_rsa.c
new file mode 100644
index 0000000000..69d69c76f4
--- /dev/null
+++ b/ruby_1_8_5/ext/openssl/ossl_pkey_rsa.c
@@ -0,0 +1,513 @@
+/*
+ * $Id: ossl_pkey_rsa.c,v 1.5.2.4 2005/09/18 22:56:11 gotoyuzo Exp $
+ * '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(OPENSSL_NO_RSA)
+
+#include "ossl.h"
+
+#define GetPKeyRSA(obj, pkey) do { \
+ GetPKey(obj, pkey); \
+ if (EVP_PKEY_type(pkey->type) != EVP_PKEY_RSA) { /* PARANOIA? */ \
+ ossl_raise(rb_eRuntimeError, "THIS IS NOT A RSA!") ; \
+ } \
+} while (0)
+
+#define RSA_HAS_PRIVATE(rsa) ((rsa)->p && (rsa)->q)
+#define RSA_PRIVATE(obj,rsa) (RSA_HAS_PRIVATE(rsa)||OSSL_PKEY_IS_PRIVATE(obj))
+
+/*
+ * Classes
+ */
+VALUE cRSA;
+VALUE eRSAError;
+
+/*
+ * Public
+ */
+static VALUE
+rsa_instance(VALUE klass, RSA *rsa)
+{
+ EVP_PKEY *pkey;
+ VALUE obj;
+
+ 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;
+}
+
+VALUE
+ossl_rsa_new(EVP_PKEY *pkey)
+{
+ VALUE obj;
+
+ if (!pkey) {
+ obj = rsa_instance(cRSA, RSA_new());
+ }
+ else {
+ if (EVP_PKEY_type(pkey->type) != EVP_PKEY_RSA) {
+ ossl_raise(rb_eTypeError, "Not a RSA key!");
+ }
+ WrapPKey(cRSA, obj, pkey);
+ }
+ if (obj == Qfalse) {
+ ossl_raise(eRSAError, NULL);
+ }
+
+ return obj;
+}
+
+/*
+ * Private
+ */
+static RSA *
+rsa_generate(int size, int exp)
+{
+ return RSA_generate_key(size, exp,
+ rb_block_given_p() ? ossl_generate_cb : NULL,
+ NULL);
+}
+
+static VALUE
+ossl_rsa_s_generate(int argc, VALUE *argv, VALUE klass)
+{
+ RSA *rsa;
+ VALUE size, exp;
+ VALUE obj;
+
+ rb_scan_args(argc, argv, "11", &size, &exp);
+
+ rsa = rsa_generate(NUM2INT(size), NIL_P(exp) ? RSA_F4 : NUM2INT(exp)); /* err handled by rsa_instance */
+ obj = rsa_instance(klass, rsa);
+
+ if (obj == Qfalse) {
+ RSA_free(rsa);
+ ossl_raise(eRSAError, NULL);
+ }
+
+ return obj;
+}
+
+static VALUE
+ossl_rsa_initialize(int argc, VALUE *argv, VALUE self)
+{
+ EVP_PKEY *pkey;
+ RSA *rsa;
+ BIO *in;
+ char *passwd = NULL;
+ VALUE arg, pass;
+
+ GetPKey(self, pkey);
+ if(rb_scan_args(argc, argv, "02", &arg, &pass) == 0) {
+ rsa = RSA_new();
+ }
+ else if (FIXNUM_P(arg)) {
+ rsa = rsa_generate(FIX2INT(arg), NIL_P(pass) ? RSA_F4 : NUM2INT(pass));
+ if (!rsa) ossl_raise(eRSAError, NULL);
+ }
+ else {
+ 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);
+ }
+ if (!rsa) {
+ 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);
+ ossl_raise(eRSAError, NULL);
+ }
+
+ return self;
+}
+
+static VALUE
+ossl_rsa_is_public(VALUE self)
+{
+ EVP_PKEY *pkey;
+
+ GetPKeyRSA(self, pkey);
+ /*
+ * SURPRISE! :-))
+ * Every key is public at the same time!
+ */
+ return Qtrue;
+}
+
+static VALUE
+ossl_rsa_is_private(VALUE self)
+{
+ EVP_PKEY *pkey;
+
+ GetPKeyRSA(self, pkey);
+
+ return (RSA_PRIVATE(self, pkey->pkey.rsa)) ? Qtrue : Qfalse;
+}
+
+static VALUE
+ossl_rsa_export(int argc, VALUE *argv, VALUE self)
+{
+ EVP_PKEY *pkey;
+ BIO *out;
+ const EVP_CIPHER *ciph = NULL;
+ char *passwd = NULL;
+ VALUE cipher, pass, str;
+
+ GetPKeyRSA(self, pkey);
+
+ rb_scan_args(argc, argv, "02", &cipher, &pass);
+
+ if (!NIL_P(cipher)) {
+ ciph = GetCipherPtr(cipher);
+ if (!NIL_P(pass)) {
+ passwd = StringValuePtr(pass);
+ }
+ }
+ if (!(out = BIO_new(BIO_s_mem()))) {
+ ossl_raise(eRSAError, NULL);
+ }
+ if (RSA_HAS_PRIVATE(pkey->pkey.rsa)) {
+ if (!PEM_write_bio_RSAPrivateKey(out, pkey->pkey.rsa, ciph,
+ NULL, 0, ossl_pem_passwd_cb, passwd)) {
+ BIO_free(out);
+ ossl_raise(eRSAError, NULL);
+ }
+ } else {
+ if (!PEM_write_bio_RSAPublicKey(out, pkey->pkey.rsa)) {
+ BIO_free(out);
+ ossl_raise(eRSAError, NULL);
+ }
+ }
+ str = ossl_membio2str(out);
+
+ return str;
+}
+
+static VALUE
+ossl_rsa_to_der(VALUE self)
+{
+ EVP_PKEY *pkey;
+ int (*i2d_func)_((const RSA*, unsigned char**));
+ unsigned char *p;
+ long len;
+ VALUE str;
+
+ GetPKeyRSA(self, pkey);
+ if(RSA_HAS_PRIVATE(pkey->pkey.rsa))
+ i2d_func = i2d_RSAPrivateKey;
+ else
+ i2d_func = i2d_RSAPublicKey;
+ if((len = i2d_func(pkey->pkey.rsa, NULL)) <= 0)
+ ossl_raise(eRSAError, NULL);
+ str = rb_str_new(0, len);
+ p = RSTRING(str)->ptr;
+ if(i2d_func(pkey->pkey.rsa, &p) < 0)
+ ossl_raise(eRSAError, NULL);
+ ossl_str_adjust(str, p);
+
+ return str;
+}
+
+#define ossl_rsa_buf_size(pkey) (RSA_size((pkey)->pkey.rsa)+16)
+
+static VALUE
+ossl_rsa_public_encrypt(int argc, VALUE *argv, VALUE self)
+{
+ EVP_PKEY *pkey;
+ int buf_len, pad;
+ VALUE str, buffer, padding;
+
+ GetPKeyRSA(self, pkey);
+ rb_scan_args(argc, argv, "11", &buffer, &padding);
+ pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding);
+ StringValue(buffer);
+ str = rb_str_new(0, ossl_rsa_buf_size(pkey));
+ buf_len = RSA_public_encrypt(RSTRING(buffer)->len, RSTRING(buffer)->ptr,
+ RSTRING(str)->ptr, pkey->pkey.rsa,
+ pad);
+ if (buf_len < 0) ossl_raise(eRSAError, NULL);
+ RSTRING(str)->len = buf_len;
+ RSTRING(str)->ptr[buf_len] = 0;
+
+ return str;
+}
+
+static VALUE
+ossl_rsa_public_decrypt(int argc, VALUE *argv, VALUE self)
+{
+ EVP_PKEY *pkey;
+ int buf_len, pad;
+ VALUE str, buffer, padding;
+
+ GetPKeyRSA(self, pkey);
+ rb_scan_args(argc, argv, "11", &buffer, &padding);
+ pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding);
+ StringValue(buffer);
+ str = rb_str_new(0, ossl_rsa_buf_size(pkey));
+ buf_len = RSA_public_decrypt(RSTRING(buffer)->len, RSTRING(buffer)->ptr,
+ RSTRING(str)->ptr, pkey->pkey.rsa,
+ pad);
+ if (buf_len < 0) ossl_raise(eRSAError, NULL);
+ RSTRING(str)->len = buf_len;
+ RSTRING(str)->ptr[buf_len] = 0;
+
+ return str;
+}
+
+static VALUE
+ossl_rsa_private_encrypt(int argc, VALUE *argv, VALUE self)
+{
+ EVP_PKEY *pkey;
+ int buf_len, pad;
+ VALUE str, buffer, padding;
+
+ GetPKeyRSA(self, pkey);
+ if (!RSA_PRIVATE(self, pkey->pkey.rsa)) {
+ ossl_raise(eRSAError, "private key needed.");
+ }
+ rb_scan_args(argc, argv, "11", &buffer, &padding);
+ pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding);
+ StringValue(buffer);
+ str = rb_str_new(0, ossl_rsa_buf_size(pkey));
+ buf_len = RSA_private_encrypt(RSTRING(buffer)->len, RSTRING(buffer)->ptr,
+ RSTRING(str)->ptr, pkey->pkey.rsa,
+ pad);
+ if (buf_len < 0) ossl_raise(eRSAError, NULL);
+ RSTRING(str)->len = buf_len;
+ RSTRING(str)->ptr[buf_len] = 0;
+
+ return str;
+}
+
+static VALUE
+ossl_rsa_private_decrypt(int argc, VALUE *argv, VALUE self)
+{
+ EVP_PKEY *pkey;
+ int buf_len, pad;
+ VALUE str, buffer, padding;
+
+ GetPKeyRSA(self, pkey);
+ if (!RSA_PRIVATE(self, pkey->pkey.rsa)) {
+ ossl_raise(eRSAError, "private key needed.");
+ }
+ rb_scan_args(argc, argv, "11", &buffer, &padding);
+ pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding);
+ StringValue(buffer);
+ str = rb_str_new(0, ossl_rsa_buf_size(pkey));
+ buf_len = RSA_private_decrypt(RSTRING(buffer)->len, RSTRING(buffer)->ptr,
+ RSTRING(str)->ptr, pkey->pkey.rsa,
+ pad);
+ if (buf_len < 0) ossl_raise(eRSAError, NULL);
+ RSTRING(str)->len = buf_len;
+ RSTRING(str)->ptr[buf_len] = 0;
+
+ return str;
+}
+
+/*
+ * Stores all parameters of key to the hash
+ * INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!!
+ * Don't use :-)) (I's up to you)
+ */
+static VALUE
+ossl_rsa_get_params(VALUE self)
+{
+ EVP_PKEY *pkey;
+ VALUE hash;
+
+ GetPKeyRSA(self, pkey);
+
+ hash = rb_hash_new();
+
+ rb_hash_aset(hash, rb_str_new2("n"), ossl_bn_new(pkey->pkey.rsa->n));
+ rb_hash_aset(hash, rb_str_new2("e"), ossl_bn_new(pkey->pkey.rsa->e));
+ rb_hash_aset(hash, rb_str_new2("d"), ossl_bn_new(pkey->pkey.rsa->d));
+ rb_hash_aset(hash, rb_str_new2("p"), ossl_bn_new(pkey->pkey.rsa->p));
+ rb_hash_aset(hash, rb_str_new2("q"), ossl_bn_new(pkey->pkey.rsa->q));
+ rb_hash_aset(hash, rb_str_new2("dmp1"), ossl_bn_new(pkey->pkey.rsa->dmp1));
+ rb_hash_aset(hash, rb_str_new2("dmq1"), ossl_bn_new(pkey->pkey.rsa->dmq1));
+ rb_hash_aset(hash, rb_str_new2("iqmp"), ossl_bn_new(pkey->pkey.rsa->iqmp));
+
+ return hash;
+}
+
+/*
+ * Prints all parameters of key to buffer
+ * INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!!
+ * Don't use :-)) (It's up to you)
+ */
+static VALUE
+ossl_rsa_to_text(VALUE self)
+{
+ EVP_PKEY *pkey;
+ BIO *out;
+ VALUE str;
+
+ GetPKeyRSA(self, pkey);
+ if (!(out = BIO_new(BIO_s_mem()))) {
+ ossl_raise(eRSAError, NULL);
+ }
+ if (!RSA_print(out, pkey->pkey.rsa, 0)) { /* offset = 0 */
+ BIO_free(out);
+ ossl_raise(eRSAError, NULL);
+ }
+ str = ossl_membio2str(out);
+
+ return str;
+}
+
+/*
+ * Makes new instance RSA PUBLIC_KEY from PRIVATE_KEY
+ */
+static VALUE
+ossl_rsa_to_public_key(VALUE self)
+{
+ EVP_PKEY *pkey;
+ RSA *rsa;
+ VALUE obj;
+
+ GetPKeyRSA(self, pkey);
+ /* err check performed by rsa_instance */
+ rsa = RSAPublicKey_dup(pkey->pkey.rsa);
+ obj = rsa_instance(CLASS_OF(self), rsa);
+ if (obj == Qfalse) {
+ RSA_free(rsa);
+ ossl_raise(eRSAError, NULL);
+ }
+ return obj;
+}
+
+/*
+ * TODO: Test me
+extern BN_CTX *ossl_bn_ctx;
+
+static VALUE
+ossl_rsa_blinding_on(VALUE self)
+{
+ EVP_PKEY *pkey;
+
+ GetPKeyRSA(self, pkey);
+
+ if (RSA_blinding_on(pkey->pkey.rsa, ossl_bn_ctx) != 1) {
+ ossl_raise(eRSAError, NULL);
+ }
+ return self;
+}
+
+static VALUE
+ossl_rsa_blinding_off(VALUE self)
+{
+ EVP_PKEY *pkey;
+
+ GetPKeyRSA(self, pkey);
+ RSA_blinding_off(pkey->pkey.rsa);
+
+ return self;
+}
+ */
+
+OSSL_PKEY_BN(rsa, n);
+OSSL_PKEY_BN(rsa, e);
+OSSL_PKEY_BN(rsa, d);
+OSSL_PKEY_BN(rsa, p);
+OSSL_PKEY_BN(rsa, q);
+OSSL_PKEY_BN(rsa, dmp1);
+OSSL_PKEY_BN(rsa, dmq1);
+OSSL_PKEY_BN(rsa, iqmp);
+
+/*
+ * INIT
+ */
+#define DefRSAConst(x) rb_define_const(cRSA, #x,INT2FIX(RSA_##x))
+
+void
+Init_ossl_rsa()
+{
+ eRSAError = rb_define_class_under(mPKey, "RSAError", ePKeyError);
+
+ cRSA = rb_define_class_under(mPKey, "RSA", cPKey);
+
+ rb_define_singleton_method(cRSA, "generate", ossl_rsa_s_generate, -1);
+ 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);
+ rb_define_method(cRSA, "export", ossl_rsa_export, -1);
+ rb_define_alias(cRSA, "to_pem", "export");
+ rb_define_alias(cRSA, "to_s", "export");
+ rb_define_method(cRSA, "to_der", ossl_rsa_to_der, 0);
+ rb_define_method(cRSA, "public_key", ossl_rsa_to_public_key, 0);
+ rb_define_method(cRSA, "public_encrypt", ossl_rsa_public_encrypt, -1);
+ rb_define_method(cRSA, "public_decrypt", ossl_rsa_public_decrypt, -1);
+ rb_define_method(cRSA, "private_encrypt", ossl_rsa_private_encrypt, -1);
+ rb_define_method(cRSA, "private_decrypt", ossl_rsa_private_decrypt, -1);
+
+ DEF_OSSL_PKEY_BN(cRSA, rsa, n);
+ DEF_OSSL_PKEY_BN(cRSA, rsa, e);
+ DEF_OSSL_PKEY_BN(cRSA, rsa, d);
+ DEF_OSSL_PKEY_BN(cRSA, rsa, p);
+ DEF_OSSL_PKEY_BN(cRSA, rsa, q);
+ DEF_OSSL_PKEY_BN(cRSA, rsa, dmp1);
+ DEF_OSSL_PKEY_BN(cRSA, rsa, dmq1);
+ DEF_OSSL_PKEY_BN(cRSA, rsa, iqmp);
+
+ rb_define_method(cRSA, "params", ossl_rsa_get_params, 0);
+
+ DefRSAConst(PKCS1_PADDING);
+ DefRSAConst(SSLV23_PADDING);
+ DefRSAConst(NO_PADDING);
+ DefRSAConst(PKCS1_OAEP_PADDING);
+
+/*
+ * TODO: Test it
+ rb_define_method(cRSA, "blinding_on!", ossl_rsa_blinding_on, 0);
+ rb_define_method(cRSA, "blinding_off!", ossl_rsa_blinding_off, 0);
+ */
+}
+
+#else /* defined NO_RSA */
+# warning >>> OpenSSL is compiled without RSA support <<<
+void
+Init_ossl_rsa()
+{
+ rb_warning("OpenSSL is compiled without RSA support");
+}
+#endif /* NO_RSA */
+
diff --git a/ruby_1_8_5/ext/openssl/ossl_rand.c b/ruby_1_8_5/ext/openssl/ossl_rand.c
new file mode 100644
index 0000000000..ffd68966ca
--- /dev/null
+++ b/ruby_1_8_5/ext/openssl/ossl_rand.c
@@ -0,0 +1,130 @@
+/*
+ * $Id: ossl_rand.c,v 1.2 2003/09/17 09:05:02 gotoyuzo Exp $
+ * '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'.)
+ */
+#include "ossl.h"
+
+/*
+ * Classes
+ */
+VALUE mRandom;
+VALUE eRandomError;
+
+/*
+ * Struct
+ */
+
+/*
+ * Public
+ */
+
+/*
+ * Private
+ */
+static VALUE
+ossl_rand_seed(VALUE self, VALUE str)
+{
+ StringValue(str);
+ RAND_seed(RSTRING(str)->ptr, RSTRING(str)->len);
+
+ return str;
+}
+
+static VALUE
+ossl_rand_load_file(VALUE self, VALUE filename)
+{
+ SafeStringValue(filename);
+
+ if(!RAND_load_file(RSTRING(filename)->ptr, -1)) {
+ ossl_raise(eRandomError, NULL);
+ }
+ return Qtrue;
+}
+
+static VALUE
+ossl_rand_write_file(VALUE self, VALUE filename)
+{
+ SafeStringValue(filename);
+ if (RAND_write_file(RSTRING(filename)->ptr) == -1) {
+ ossl_raise(eRandomError, NULL);
+ }
+ return Qtrue;
+}
+
+static VALUE
+ossl_rand_bytes(VALUE self, VALUE len)
+{
+ VALUE str;
+
+ str = rb_str_new(0, FIX2INT(len));
+ if (!RAND_bytes(RSTRING(str)->ptr, FIX2INT(len))) {
+ ossl_raise(eRandomError, NULL);
+ }
+
+ return str;
+}
+
+static VALUE
+ossl_rand_pseudo_bytes(VALUE self, VALUE len)
+{
+ VALUE str;
+
+ str = rb_str_new(0, FIX2INT(len));
+ if (!RAND_pseudo_bytes(RSTRING(str)->ptr, FIX2INT(len))) {
+ ossl_raise(eRandomError, NULL);
+ }
+
+ return str;
+}
+
+static VALUE
+ossl_rand_egd(VALUE self, VALUE filename)
+{
+ SafeStringValue(filename);
+
+ if(!RAND_egd(RSTRING(filename)->ptr)) {
+ ossl_raise(eRandomError, NULL);
+ }
+ return Qtrue;
+}
+
+static VALUE
+ossl_rand_egd_bytes(VALUE self, VALUE filename, VALUE len)
+{
+ SafeStringValue(filename);
+
+ if (!RAND_egd_bytes(RSTRING(filename)->ptr, FIX2INT(len))) {
+ ossl_raise(eRandomError, NULL);
+ }
+ return Qtrue;
+}
+
+#define DEFMETH(class, name, func, argc) \
+ rb_define_method(class, name, func, argc); \
+ rb_define_singleton_method(class, name, func, argc);
+
+/*
+ * INIT
+ */
+void
+Init_ossl_rand()
+{
+ mRandom = rb_define_module_under(mOSSL, "Random");
+
+ eRandomError = rb_define_class_under(mRandom, "RandomError", eOSSLError);
+
+ DEFMETH(mRandom, "seed", ossl_rand_seed, 1);
+ DEFMETH(mRandom, "load_random_file", ossl_rand_load_file, 1);
+ DEFMETH(mRandom, "write_random_file", ossl_rand_write_file, 1);
+ DEFMETH(mRandom, "random_bytes", ossl_rand_bytes, 1);
+ DEFMETH(mRandom, "pseudo_bytes", ossl_rand_pseudo_bytes, 1);
+ DEFMETH(mRandom, "egd", ossl_rand_egd, 1);
+ DEFMETH(mRandom, "egd_bytes", ossl_rand_egd_bytes, 2);
+}
+
diff --git a/ruby_1_8_5/ext/openssl/ossl_rand.h b/ruby_1_8_5/ext/openssl/ossl_rand.h
new file mode 100644
index 0000000000..4895267fb6
--- /dev/null
+++ b/ruby_1_8_5/ext/openssl/ossl_rand.h
@@ -0,0 +1,20 @@
+/*
+ * $Id: ossl_rand.h,v 1.1 2003/07/23 16:11:29 gotoyuzo Exp $
+ * '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_RAND_H_)
+#define _OSSL_RAND_H_
+
+extern VALUE mRandom;
+extern VALUE eRandomError;
+
+void Init_ossl_rand(void);
+
+#endif /* _OSSL_RAND_H_ */
+
diff --git a/ruby_1_8_5/ext/openssl/ossl_ssl.c b/ruby_1_8_5/ext/openssl/ossl_ssl.c
new file mode 100644
index 0000000000..e4889d6d3f
--- /dev/null
+++ b/ruby_1_8_5/ext/openssl/ossl_ssl.c
@@ -0,0 +1,937 @@
+/*
+ * $Id: ossl_ssl.c,v 1.13.2.11 2006/03/17 10:10:53 gotoyuzo Exp $
+ * 'OpenSSL for Ruby' project
+ * Copyright (C) 2000-2002 GOTOU Yuuzou <gotoyuzo@notwork.org>
+ * 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'.)
+ */
+#include "ossl.h"
+#include <rubysig.h>
+#include <rubyio.h>
+
+#if defined(HAVE_UNISTD_H)
+# include <unistd.h> /* for read(), and write() */
+#endif
+
+#define numberof(ary) (sizeof(ary)/sizeof(ary[0]))
+
+#ifdef _WIN32
+# define TO_SOCKET(s) _get_osfhandle(s)
+#else
+# define TO_SOCKET(s) s
+#endif
+
+VALUE mSSL;
+VALUE eSSLError;
+VALUE cSSLContext;
+VALUE cSSLSocket;
+
+/*
+ * SSLContext class
+ */
+#define ossl_sslctx_set_cert(o,v) rb_iv_set((o),"@cert",(v))
+#define ossl_sslctx_set_key(o,v) rb_iv_set((o),"@key",(v))
+#define ossl_sslctx_set_client_ca(o,v) rb_iv_set((o),"@client_ca",(v))
+#define ossl_sslctx_set_ca_file(o,v) rb_iv_set((o),"@ca_file",(v))
+#define ossl_sslctx_set_ca_path(o,v) rb_iv_set((o),"@ca_path",(v))
+#define ossl_sslctx_set_timeout(o,v) rb_iv_set((o),"@timeout",(v))
+#define ossl_sslctx_set_verify_mode(o,v) rb_iv_set((o),"@verify_mode",(v))
+#define ossl_sslctx_set_verify_dep(o,v) rb_iv_set((o),"@verify_depth",(v))
+#define ossl_sslctx_set_verify_cb(o,v) rb_iv_set((o),"@verify_callback",(v))
+#define ossl_sslctx_set_options(o,v) rb_iv_set((o),"@options",(v))
+#define ossl_sslctx_set_cert_store(o,v) rb_iv_set((o),"@cert_store",(v))
+#define ossl_sslctx_set_extra_cert(o,v) rb_iv_set((o),"@extra_chain_cert",(v))
+#define ossl_sslctx_set_client_cert_cb(o,v) rb_iv_set((o),"@client_cert_cb",(v))
+#define ossl_sslctx_set_tmp_dh_cb(o,v) rb_iv_set((o),"@tmp_dh_callback",(v))
+#define ossl_sslctx_set_sess_id_ctx(o, v) rb_iv_get((o),"@session_id_context"(v))
+
+#define ossl_sslctx_get_cert(o) rb_iv_get((o),"@cert")
+#define ossl_sslctx_get_key(o) rb_iv_get((o),"@key")
+#define ossl_sslctx_get_client_ca(o) rb_iv_get((o),"@client_ca")
+#define ossl_sslctx_get_ca_file(o) rb_iv_get((o),"@ca_file")
+#define ossl_sslctx_get_ca_path(o) rb_iv_get((o),"@ca_path")
+#define ossl_sslctx_get_timeout(o) rb_iv_get((o),"@timeout")
+#define ossl_sslctx_get_verify_mode(o) rb_iv_get((o),"@verify_mode")
+#define ossl_sslctx_get_verify_dep(o) rb_iv_get((o),"@verify_depth")
+#define ossl_sslctx_get_verify_cb(o) rb_iv_get((o),"@verify_callback")
+#define ossl_sslctx_get_options(o) rb_iv_get((o),"@options")
+#define ossl_sslctx_get_cert_store(o) rb_iv_get((o),"@cert_store")
+#define ossl_sslctx_get_extra_cert(o) rb_iv_get((o),"@extra_chain_cert")
+#define ossl_sslctx_get_client_cert_cb(o) rb_iv_get((o),"@client_cert_cb")
+#define ossl_sslctx_get_tmp_dh_cb(o) rb_iv_get((o),"@tmp_dh_callback")
+#define ossl_sslctx_get_sess_id_ctx(o) rb_iv_get((o),"@session_id_context")
+
+static char *ossl_sslctx_attrs[] = {
+ "cert", "key", "client_ca", "ca_file", "ca_path",
+ "timeout", "verify_mode", "verify_depth",
+ "verify_callback", "options", "cert_store", "extra_chain_cert",
+ "client_cert_cb", "tmp_dh_callback", "session_id_context",
+};
+
+#define ossl_ssl_get_io(o) rb_iv_get((o),"@io")
+#define ossl_ssl_get_ctx(o) rb_iv_get((o),"@context")
+#define ossl_ssl_get_sync_close(o) rb_iv_get((o),"@sync_close")
+#define ossl_ssl_get_x509(o) rb_iv_get((o),"@x509")
+#define ossl_ssl_get_key(o) rb_iv_get((o),"@key")
+#define ossl_ssl_get_tmp_dh(o) rb_iv_get((o),"@tmp_dh")
+
+#define ossl_ssl_set_io(o,v) rb_iv_set((o),"@io",(v))
+#define ossl_ssl_set_ctx(o,v) rb_iv_set((o),"@context",(v))
+#define ossl_ssl_set_sync_close(o,v) rb_iv_set((o),"@sync_close",(v))
+#define ossl_ssl_set_x509(o,v) rb_iv_set((o),"@x509",(v))
+#define ossl_ssl_set_key(o,v) rb_iv_set((o),"@key",(v))
+#define ossl_ssl_set_tmp_dh(o,v) rb_iv_set((o),"@tmp_dh",(v))
+
+static char *ossl_ssl_attr_readers[] = { "io", "context", };
+static char *ossl_ssl_attrs[] = { "sync_close", };
+
+/*
+ * SSLContext class
+ */
+struct {
+ const char *name;
+ SSL_METHOD *(*func)(void);
+} ossl_ssl_method_tab[] = {
+#define OSSL_SSL_METHOD_ENTRY(name) { #name, name##_method }
+ OSSL_SSL_METHOD_ENTRY(TLSv1),
+ OSSL_SSL_METHOD_ENTRY(TLSv1_server),
+ OSSL_SSL_METHOD_ENTRY(TLSv1_client),
+ OSSL_SSL_METHOD_ENTRY(SSLv2),
+ OSSL_SSL_METHOD_ENTRY(SSLv2_server),
+ OSSL_SSL_METHOD_ENTRY(SSLv2_client),
+ OSSL_SSL_METHOD_ENTRY(SSLv3),
+ OSSL_SSL_METHOD_ENTRY(SSLv3_server),
+ OSSL_SSL_METHOD_ENTRY(SSLv3_client),
+ OSSL_SSL_METHOD_ENTRY(SSLv23),
+ OSSL_SSL_METHOD_ENTRY(SSLv23_server),
+ OSSL_SSL_METHOD_ENTRY(SSLv23_client),
+#undef OSSL_SSL_METHOD_ENTRY
+};
+
+int ossl_ssl_ex_vcb_idx;
+int ossl_ssl_ex_store_p;
+int ossl_ssl_ex_ptr_idx;
+int ossl_ssl_ex_client_cert_cb_idx;
+int ossl_ssl_ex_tmp_dh_callback_idx;
+
+static void
+ossl_sslctx_free(SSL_CTX *ctx)
+{
+ if(ctx && SSL_CTX_get_ex_data(ctx, ossl_ssl_ex_store_p)== (void*)1)
+ ctx->cert_store = NULL;
+ SSL_CTX_free(ctx);
+}
+
+static VALUE
+ossl_sslctx_s_alloc(VALUE klass)
+{
+ SSL_CTX *ctx;
+
+ ctx = SSL_CTX_new(SSLv23_method());
+ if (!ctx) {
+ ossl_raise(eSSLError, "SSL_CTX_new:");
+ }
+ SSL_CTX_set_mode(ctx, SSL_MODE_ENABLE_PARTIAL_WRITE);
+ SSL_CTX_set_options(ctx, SSL_OP_ALL);
+ return Data_Wrap_Struct(klass, 0, ossl_sslctx_free, ctx);
+}
+
+static VALUE
+ossl_sslctx_initialize(int argc, VALUE *argv, VALUE self)
+{
+ VALUE ssl_method;
+ SSL_METHOD *method = NULL;
+ SSL_CTX *ctx;
+ int i;
+ char *s;
+
+ for(i = 0; i < numberof(ossl_sslctx_attrs); i++){
+ char buf[32];
+ snprintf(buf, sizeof(buf), "@%s", ossl_sslctx_attrs[i]);
+ rb_iv_set(self, buf, Qnil);
+ }
+ if (rb_scan_args(argc, argv, "01", &ssl_method) == 0){
+ return self;
+ }
+ if(TYPE(ssl_method) == T_SYMBOL)
+ s = rb_id2name(SYM2ID(ssl_method));
+ else
+ s = StringValuePtr(ssl_method);
+ for (i = 0; i < numberof(ossl_ssl_method_tab); i++) {
+ if (strcmp(ossl_ssl_method_tab[i].name, s) == 0) {
+ method = ossl_ssl_method_tab[i].func();
+ break;
+ }
+ }
+ if (!method) {
+ ossl_raise(rb_eArgError, "unknown SSL method `%s'.", s);
+ }
+ Data_Get_Struct(self, SSL_CTX, ctx);
+ if (SSL_CTX_set_ssl_version(ctx, method) != 1) {
+ ossl_raise(eSSLError, "SSL_CTX_set_ssl_version:");
+ }
+
+ return self;
+}
+
+static VALUE
+ossl_call_client_cert_cb(VALUE obj)
+{
+ VALUE cb, ary, cert, key;
+ SSL *ssl;
+
+ Data_Get_Struct(obj, SSL, ssl);
+ cb = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_client_cert_cb_idx);
+ if (NIL_P(cb)) return Qfalse;
+ ary = rb_funcall(cb, rb_intern("call"), 1, obj);
+ Check_Type(ary, T_ARRAY);
+ GetX509CertPtr(cert = rb_ary_entry(ary, 0));
+ GetPKeyPtr(key = rb_ary_entry(ary, 1));
+ ossl_ssl_set_x509(obj, cert);
+ ossl_ssl_set_key(obj, key);
+
+ return Qtrue;
+}
+
+static int
+ossl_client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
+{
+ VALUE obj;
+ int status, success;
+
+ obj = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx);
+ success = rb_protect((VALUE(*)_((VALUE)))ossl_call_client_cert_cb,
+ obj, &status);
+ if (status || !success) return 0;
+ *x509 = DupX509CertPtr(ossl_ssl_get_x509(obj));
+ *pkey = DupPKeyPtr(ossl_ssl_get_key(obj));
+
+ return 1;
+}
+
+#if !defined(OPENSSL_NO_DH)
+static VALUE
+ossl_call_tmp_dh_callback(VALUE *args)
+{
+ SSL *ssl;
+ VALUE cb, dh;
+ EVP_PKEY *pkey;
+
+ Data_Get_Struct(args[0], SSL, ssl);
+ cb = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_tmp_dh_callback_idx);
+ if (NIL_P(cb)) return Qfalse;
+ dh = rb_funcall(cb, rb_intern("call"), 3, args[0], args[1], args[2]);
+ pkey = GetPKeyPtr(dh);
+ if (EVP_PKEY_type(pkey->type) != EVP_PKEY_DH) return Qfalse;
+ ossl_ssl_set_tmp_dh(args[0], dh);
+
+ return Qtrue;
+}
+
+static DH*
+ossl_tmp_dh_callback(SSL *ssl, int is_export, int keylength)
+{
+ VALUE args[3];
+ int status, success;
+
+ args[0] = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx);
+ args[1] = INT2FIX(is_export);
+ args[2] = INT2FIX(keylength);
+ success = rb_protect((VALUE(*)_((VALUE)))ossl_call_tmp_dh_callback,
+ (VALUE)args, &status);
+ if (status || !success) return NULL;
+
+ return GetPKeyPtr(ossl_ssl_get_tmp_dh(args[0]))->pkey.dh;
+}
+
+static DH*
+ossl_default_tmp_dh_callback(SSL *ssl, int is_export, int keylength)
+{
+ switch(keylength){
+ case 512:
+ return OSSL_DEFAULT_DH_512;
+ case 1024:
+ return OSSL_DEFAULT_DH_1024;
+ }
+ return NULL;
+}
+#endif /* OPENSSL_NO_DH */
+
+static int
+ossl_ssl_verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
+{
+ VALUE cb;
+ SSL *ssl;
+
+ ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
+ cb = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_vcb_idx);
+ X509_STORE_CTX_set_ex_data(ctx, ossl_verify_cb_idx, (void*)cb);
+ return ossl_verify_cb(preverify_ok, ctx);
+}
+
+static VALUE
+ossl_sslctx_add_extra_chain_cert_i(VALUE i, VALUE arg)
+{
+ X509 *x509;
+ SSL_CTX *ctx;
+
+ Data_Get_Struct(arg, SSL_CTX, ctx);
+ x509 = DupX509CertPtr(i);
+ if(!SSL_CTX_add_extra_chain_cert(ctx, x509)){
+ ossl_raise(eSSLError, NULL);
+ }
+
+ return i;
+}
+
+static VALUE
+ossl_sslctx_setup(VALUE self)
+{
+ SSL_CTX *ctx;
+ X509 *cert = NULL, *client_ca = NULL;
+ X509_STORE *store;
+ EVP_PKEY *key = NULL;
+ char *ca_path = NULL, *ca_file = NULL;
+ int i, verify_mode;
+ VALUE val;
+
+ if(OBJ_FROZEN(self)) return Qnil;
+ Data_Get_Struct(self, SSL_CTX, ctx);
+
+#if !defined(OPENSSL_NO_DH)
+ if (RTEST(ossl_sslctx_get_tmp_dh_cb(self))){
+ SSL_CTX_set_tmp_dh_callback(ctx, ossl_tmp_dh_callback);
+ }
+ else{
+ rb_warning("using default DH parameters.");
+ SSL_CTX_set_tmp_dh_callback(ctx, ossl_default_tmp_dh_callback);
+ }
+#endif
+
+ val = ossl_sslctx_get_cert_store(self);
+ if(!NIL_P(val)){
+ /*
+ * WORKAROUND:
+ * X509_STORE can count references, but
+ * X509_STORE_free() doesn't care it.
+ * So we won't increment it but mark it by ex_data.
+ */
+ store = GetX509StorePtr(val); /* NO NEED TO DUP */
+ SSL_CTX_set_cert_store(ctx, store);
+ SSL_CTX_set_ex_data(ctx, ossl_ssl_ex_store_p, (void*)1);
+ }
+
+ val = ossl_sslctx_get_extra_cert(self);
+ if(!NIL_P(val)){
+ rb_iterate(rb_each, val, ossl_sslctx_add_extra_chain_cert_i, self);
+ }
+
+ /* private key may be bundled in certificate file. */
+ val = ossl_sslctx_get_cert(self);
+ cert = NIL_P(val) ? NULL : GetX509CertPtr(val); /* NO DUP NEEDED */
+ val = ossl_sslctx_get_key(self);
+ key = NIL_P(val) ? NULL : GetPKeyPtr(val); /* NO DUP NEEDED */
+ if (cert && key) {
+ if (!SSL_CTX_use_certificate(ctx, cert)) {
+ /* Adds a ref => Safe to FREE */
+ ossl_raise(eSSLError, "SSL_CTX_use_certificate:");
+ }
+ if (!SSL_CTX_use_PrivateKey(ctx, key)) {
+ /* Adds a ref => Safe to FREE */
+ ossl_raise(eSSLError, "SSL_CTX_use_PrivateKey:");
+ }
+ if (!SSL_CTX_check_private_key(ctx)) {
+ ossl_raise(eSSLError, "SSL_CTX_check_private_key:");
+ }
+ }
+
+ val = ossl_sslctx_get_client_ca(self);
+ if(!NIL_P(val)){
+ if(TYPE(val) == T_ARRAY){
+ for(i = 0; i < RARRAY(val)->len; i++){
+ client_ca = GetX509CertPtr(RARRAY(val)->ptr[i]);
+ if (!SSL_CTX_add_client_CA(ctx, client_ca)){
+ /* Copies X509_NAME => FREE it. */
+ ossl_raise(eSSLError, "SSL_CTX_add_client_CA");
+ }
+ }
+ }
+ else{
+ client_ca = GetX509CertPtr(val); /* NO DUP NEEDED. */
+ if (!SSL_CTX_add_client_CA(ctx, client_ca)){
+ /* Copies X509_NAME => FREE it. */
+ ossl_raise(eSSLError, "SSL_CTX_add_client_CA");
+ }
+ }
+ }
+
+ val = ossl_sslctx_get_ca_file(self);
+ ca_file = NIL_P(val) ? NULL : StringValuePtr(val);
+ val = ossl_sslctx_get_ca_path(self);
+ ca_path = NIL_P(val) ? NULL : StringValuePtr(val);
+ if(ca_file || ca_path){
+ if (!SSL_CTX_load_verify_locations(ctx, ca_file, ca_path))
+ rb_warning("can't set verify locations");
+ }
+
+ val = ossl_sslctx_get_verify_mode(self);
+ verify_mode = NIL_P(val) ? SSL_VERIFY_NONE : NUM2INT(val);
+ SSL_CTX_set_verify(ctx, verify_mode, ossl_ssl_verify_callback);
+ if (RTEST(ossl_sslctx_get_client_cert_cb(self)))
+ SSL_CTX_set_client_cert_cb(ctx, ossl_client_cert_cb);
+
+ val = ossl_sslctx_get_timeout(self);
+ if(!NIL_P(val)) SSL_CTX_set_timeout(ctx, NUM2LONG(val));
+
+ val = ossl_sslctx_get_verify_dep(self);
+ if(!NIL_P(val)) SSL_CTX_set_verify_depth(ctx, NUM2LONG(val));
+
+ val = ossl_sslctx_get_options(self);
+ if(!NIL_P(val)) SSL_CTX_set_options(ctx, NUM2LONG(val));
+ rb_obj_freeze(self);
+
+ val = ossl_sslctx_get_sess_id_ctx(self);
+ if (!NIL_P(val)){
+ StringValue(val);
+ if (!SSL_CTX_set_session_id_context(ctx, RSTRING(val)->ptr,
+ RSTRING(val)->len)){
+ ossl_raise(eSSLError, "SSL_CTX_set_session_id_context:");
+ }
+ }
+
+ return Qtrue;
+}
+
+static VALUE
+ossl_ssl_cipher_to_ary(SSL_CIPHER *cipher)
+{
+ VALUE ary;
+ int bits, alg_bits;
+
+ ary = rb_ary_new2(4);
+ rb_ary_push(ary, rb_str_new2(SSL_CIPHER_get_name(cipher)));
+ rb_ary_push(ary, rb_str_new2(SSL_CIPHER_get_version(cipher)));
+ bits = SSL_CIPHER_get_bits(cipher, &alg_bits);
+ rb_ary_push(ary, INT2FIX(bits));
+ rb_ary_push(ary, INT2FIX(alg_bits));
+
+ return ary;
+}
+
+static VALUE
+ossl_sslctx_get_ciphers(VALUE self)
+{
+ SSL_CTX *ctx;
+ STACK_OF(SSL_CIPHER) *ciphers;
+ SSL_CIPHER *cipher;
+ VALUE ary;
+ int i, num;
+
+ Data_Get_Struct(self, SSL_CTX, ctx);
+ if(!ctx){
+ rb_warning("SSL_CTX is not initialized.");
+ return Qnil;
+ }
+ ciphers = ctx->cipher_list;
+
+ if (!ciphers)
+ return rb_ary_new();
+
+ num = sk_num((STACK*)ciphers);
+ ary = rb_ary_new2(num);
+ for(i = 0; i < num; i++){
+ cipher = (SSL_CIPHER*)sk_value((STACK*)ciphers, i);
+ rb_ary_push(ary, ossl_ssl_cipher_to_ary(cipher));
+ }
+ return ary;
+}
+
+static VALUE
+ossl_sslctx_set_ciphers(VALUE self, VALUE v)
+{
+ SSL_CTX *ctx;
+ VALUE str, elem;
+ int i;
+
+ rb_check_frozen(self);
+ if (NIL_P(v))
+ return v;
+ else if (TYPE(v) == T_ARRAY) {
+ str = rb_str_new(0, 0);
+ for (i = 0; i < RARRAY(v)->len; i++) {
+ elem = rb_ary_entry(v, i);
+ if (TYPE(elem) == T_ARRAY) elem = rb_ary_entry(elem, 0);
+ elem = rb_String(elem);
+ rb_str_append(str, elem);
+ if (i < RARRAY(v)->len-1) rb_str_cat2(str, ":");
+ }
+ } else {
+ str = v;
+ StringValue(str);
+ }
+
+ Data_Get_Struct(self, SSL_CTX, ctx);
+ if(!ctx){
+ ossl_raise(eSSLError, "SSL_CTX is not initialized.");
+ return Qnil;
+ }
+ if (!SSL_CTX_set_cipher_list(ctx, RSTRING(str)->ptr)) {
+ ossl_raise(eSSLError, "SSL_CTX_set_cipher_list:");
+ }
+
+ return v;
+}
+
+/*
+ * SSLSocket class
+ */
+static void
+ossl_ssl_shutdown(SSL *ssl)
+{
+ if (ssl) {
+ SSL_shutdown(ssl);
+ SSL_clear(ssl);
+ }
+}
+
+static void
+ossl_ssl_free(SSL *ssl)
+{
+ ossl_ssl_shutdown(ssl);
+ SSL_free(ssl);
+}
+
+static VALUE
+ossl_ssl_s_alloc(VALUE klass)
+{
+ return Data_Wrap_Struct(klass, 0, ossl_ssl_free, NULL);
+}
+
+static VALUE
+ossl_ssl_initialize(int argc, VALUE *argv, VALUE self)
+{
+ VALUE io, ctx;
+
+ if (rb_scan_args(argc, argv, "11", &io, &ctx) == 1) {
+ ctx = rb_funcall(cSSLContext, rb_intern("new"), 0);
+ }
+ OSSL_Check_Kind(ctx, cSSLContext);
+ Check_Type(io, T_FILE);
+ ossl_ssl_set_io(self, io);
+ ossl_ssl_set_ctx(self, ctx);
+ ossl_ssl_set_sync_close(self, Qfalse);
+ ossl_sslctx_setup(ctx);
+ rb_call_super(0, 0);
+
+ return self;
+}
+
+static VALUE
+ossl_ssl_setup(VALUE self)
+{
+ VALUE io, v_ctx, cb;
+ SSL_CTX *ctx;
+ SSL *ssl;
+ OpenFile *fptr;
+
+ Data_Get_Struct(self, SSL, ssl);
+ if(!ssl){
+ v_ctx = ossl_ssl_get_ctx(self);
+ Data_Get_Struct(v_ctx, SSL_CTX, ctx);
+
+ ssl = SSL_new(ctx);
+ if (!ssl) {
+ ossl_raise(eSSLError, "SSL_new:");
+ }
+ DATA_PTR(self) = ssl;
+
+ io = ossl_ssl_get_io(self);
+ GetOpenFile(io, fptr);
+ rb_io_check_readable(fptr);
+ rb_io_check_writable(fptr);
+ SSL_set_fd(ssl, TO_SOCKET(fileno(fptr->f)));
+ SSL_set_ex_data(ssl, ossl_ssl_ex_ptr_idx, (void*)self);
+ cb = ossl_sslctx_get_verify_cb(v_ctx);
+ SSL_set_ex_data(ssl, ossl_ssl_ex_vcb_idx, (void*)cb);
+ cb = ossl_sslctx_get_client_cert_cb(v_ctx);
+ SSL_set_ex_data(ssl, ossl_ssl_ex_client_cert_cb_idx, (void*)cb);
+ cb = ossl_sslctx_get_tmp_dh_cb(v_ctx);
+ SSL_set_ex_data(ssl, ossl_ssl_ex_tmp_dh_callback_idx, (void*)cb);
+ }
+
+ return Qtrue;
+}
+
+#ifdef _WIN32
+#define ssl_get_error(ssl, ret) \
+ (errno = WSAGetLastError(), SSL_get_error(ssl, ret))
+#else
+#define ssl_get_error(ssl, ret) SSL_get_error(ssl, ret)
+#endif
+
+static VALUE
+ossl_start_ssl(VALUE self, int (*func)())
+{
+ SSL *ssl;
+ OpenFile *fptr;
+ int ret;
+
+ Data_Get_Struct(self, SSL, ssl);
+ GetOpenFile(ossl_ssl_get_io(self), fptr);
+ for(;;){
+ if((ret = func(ssl)) > 0) break;
+ switch(ssl_get_error(ssl, ret)){
+ case SSL_ERROR_WANT_WRITE:
+ rb_io_wait_writable(fileno(fptr->f));
+ continue;
+ case SSL_ERROR_WANT_READ:
+ rb_io_wait_readable(fileno(fptr->f));
+ continue;
+ case SSL_ERROR_SYSCALL:
+ if (errno) rb_sys_fail(0);
+ default:
+ ossl_raise(eSSLError, NULL);
+ }
+ }
+
+ return self;
+}
+
+static VALUE
+ossl_ssl_connect(VALUE self)
+{
+ ossl_ssl_setup(self);
+ return ossl_start_ssl(self, SSL_connect);
+}
+
+static VALUE
+ossl_ssl_accept(VALUE self)
+{
+ ossl_ssl_setup(self);
+ return ossl_start_ssl(self, SSL_accept);
+}
+
+static VALUE
+ossl_ssl_read(int argc, VALUE *argv, VALUE self)
+{
+ SSL *ssl;
+ int ilen, nread = 0;
+ VALUE len, str;
+ OpenFile *fptr;
+
+ rb_scan_args(argc, argv, "11", &len, &str);
+ ilen = NUM2INT(len);
+ if(NIL_P(str)) str = rb_str_new(0, ilen);
+ else{
+ StringValue(str);
+ rb_str_modify(str);
+ rb_str_resize(str, ilen);
+ }
+ if(ilen == 0) return str;
+
+ Data_Get_Struct(self, SSL, ssl);
+ GetOpenFile(ossl_ssl_get_io(self), fptr);
+ if (ssl) {
+ if(SSL_pending(ssl) <= 0)
+ rb_thread_wait_fd(fileno(fptr->f));
+ for (;;){
+ nread = SSL_read(ssl, RSTRING(str)->ptr, RSTRING(str)->len);
+ switch(ssl_get_error(ssl, nread)){
+ case SSL_ERROR_NONE:
+ goto end;
+ case SSL_ERROR_ZERO_RETURN:
+ rb_eof_error();
+ case SSL_ERROR_WANT_WRITE:
+ rb_io_wait_writable(fileno(fptr->f));
+ continue;
+ case SSL_ERROR_WANT_READ:
+ rb_io_wait_readable(fileno(fptr->f));
+ continue;
+ case SSL_ERROR_SYSCALL:
+ if(ERR_peek_error() == 0 && nread == 0) rb_eof_error();
+ rb_sys_fail(0);
+ default:
+ ossl_raise(eSSLError, "SSL_read:");
+ }
+ }
+ }
+ else {
+ ID id_sysread = rb_intern("sysread");
+ rb_warning("SSL session is not started yet.");
+ return rb_funcall(ossl_ssl_get_io(self), id_sysread, 2, len, str);
+ }
+
+ end:
+ RSTRING(str)->len = nread;
+ RSTRING(str)->ptr[nread] = 0;
+ OBJ_TAINT(str);
+
+ return str;
+}
+
+static VALUE
+ossl_ssl_write(VALUE self, VALUE str)
+{
+ SSL *ssl;
+ int nwrite = 0;
+ OpenFile *fptr;
+
+ StringValue(str);
+ Data_Get_Struct(self, SSL, ssl);
+ GetOpenFile(ossl_ssl_get_io(self), fptr);
+
+ if (ssl) {
+ for (;;){
+ nwrite = SSL_write(ssl, RSTRING(str)->ptr, RSTRING(str)->len);
+ switch(ssl_get_error(ssl, nwrite)){
+ case SSL_ERROR_NONE:
+ goto end;
+ case SSL_ERROR_WANT_WRITE:
+ rb_io_wait_writable(fileno(fptr->f));
+ continue;
+ case SSL_ERROR_WANT_READ:
+ rb_io_wait_readable(fileno(fptr->f));
+ continue;
+ case SSL_ERROR_SYSCALL:
+ if (errno) rb_sys_fail(0);
+ default:
+ ossl_raise(eSSLError, "SSL_write:");
+ }
+ }
+ }
+ else {
+ ID id_syswrite = rb_intern("syswrite");
+ rb_warning("SSL session is not started yet.");
+ return rb_funcall(ossl_ssl_get_io(self), id_syswrite, 1, str);
+ }
+
+ end:
+ return INT2NUM(nwrite);
+}
+
+static VALUE
+ossl_ssl_close(VALUE self)
+{
+ SSL *ssl;
+
+ Data_Get_Struct(self, SSL, ssl);
+ ossl_ssl_shutdown(ssl);
+ if (RTEST(ossl_ssl_get_sync_close(self)))
+ rb_funcall(ossl_ssl_get_io(self), rb_intern("close"), 0);
+
+ return Qnil;
+}
+
+static VALUE
+ossl_ssl_get_cert(VALUE self)
+{
+ SSL *ssl;
+ X509 *cert = NULL;
+
+ Data_Get_Struct(self, SSL, ssl);
+ if (ssl) {
+ rb_warning("SSL session is not started yet.");
+ return Qnil;
+ }
+
+ /*
+ * Is this OpenSSL bug? Should add a ref?
+ * TODO: Ask for.
+ */
+ cert = SSL_get_certificate(ssl); /* NO DUPs => DON'T FREE. */
+
+ if (!cert) {
+ return Qnil;
+ }
+ return ossl_x509_new(cert);
+}
+
+static VALUE
+ossl_ssl_get_peer_cert(VALUE self)
+{
+ SSL *ssl;
+ X509 *cert = NULL;
+ VALUE obj;
+
+ Data_Get_Struct(self, SSL, ssl);
+
+ if (!ssl){
+ rb_warning("SSL session is not started yet.");
+ return Qnil;
+ }
+
+ cert = SSL_get_peer_certificate(ssl); /* Adds a ref => Safe to FREE. */
+
+ if (!cert) {
+ return Qnil;
+ }
+ obj = ossl_x509_new(cert);
+ X509_free(cert);
+
+ return obj;
+}
+
+static VALUE
+ossl_ssl_get_peer_cert_chain(VALUE self)
+{
+ SSL *ssl;
+ STACK_OF(X509) *chain;
+ X509 *cert;
+ VALUE ary;
+ int i, num;
+
+ Data_Get_Struct(self, SSL, ssl);
+ if(!ssl){
+ rb_warning("SSL session is not started yet.");
+ return Qnil;
+ }
+ chain = SSL_get_peer_cert_chain(ssl);
+ if(!chain) return Qnil;
+ num = sk_num(chain);
+ ary = rb_ary_new2(num);
+ for (i = 0; i < num; i++){
+ cert = (X509*)sk_value(chain, i);
+ rb_ary_push(ary, ossl_x509_new(cert));
+ }
+
+ return ary;
+}
+
+static VALUE
+ossl_ssl_get_cipher(VALUE self)
+{
+ SSL *ssl;
+ SSL_CIPHER *cipher;
+
+ Data_Get_Struct(self, SSL, ssl);
+ if (!ssl) {
+ rb_warning("SSL session is not started yet.");
+ return Qnil;
+ }
+ cipher = SSL_get_current_cipher(ssl);
+
+ return ossl_ssl_cipher_to_ary(cipher);
+}
+
+static VALUE
+ossl_ssl_get_state(VALUE self)
+{
+ SSL *ssl;
+ VALUE ret;
+
+ Data_Get_Struct(self, SSL, ssl);
+ if (!ssl) {
+ rb_warning("SSL session is not started yet.");
+ return Qnil;
+ }
+ ret = rb_str_new2(SSL_state_string(ssl));
+ if (ruby_verbose) {
+ rb_str_cat2(ret, ": ");
+ rb_str_cat2(ret, SSL_state_string_long(ssl));
+ }
+ return ret;
+}
+
+static VALUE
+ossl_ssl_pending(VALUE self)
+{
+ SSL *ssl;
+
+ Data_Get_Struct(self, SSL, ssl);
+ if (!ssl) {
+ rb_warning("SSL session is not started yet.");
+ return Qnil;
+ }
+
+ return INT2NUM(SSL_pending(ssl));
+}
+
+void
+Init_ossl_ssl()
+{
+ int i;
+
+ ossl_ssl_ex_vcb_idx = SSL_get_ex_new_index(0,"ossl_ssl_ex_vcb_idx",0,0,0);
+ ossl_ssl_ex_store_p = SSL_get_ex_new_index(0,"ossl_ssl_ex_store_p",0,0,0);
+ ossl_ssl_ex_ptr_idx = SSL_get_ex_new_index(0,"ossl_ssl_ex_ptr_idx",0,0,0);
+ ossl_ssl_ex_client_cert_cb_idx =
+ SSL_get_ex_new_index(0,"ossl_ssl_ex_client_cert_cb_idx",0,0,0);
+ ossl_ssl_ex_tmp_dh_callback_idx =
+ SSL_get_ex_new_index(0,"ossl_ssl_ex_tmp_dh_callback_idx",0,0,0);
+
+ mSSL = rb_define_module_under(mOSSL, "SSL");
+ eSSLError = rb_define_class_under(mSSL, "SSLError", eOSSLError);
+
+ /* class SSLContext */
+ cSSLContext = rb_define_class_under(mSSL, "SSLContext", rb_cObject);
+ rb_define_alloc_func(cSSLContext, ossl_sslctx_s_alloc);
+ for(i = 0; i < numberof(ossl_sslctx_attrs); i++)
+ rb_attr(cSSLContext, rb_intern(ossl_sslctx_attrs[i]), 1, 1, Qfalse);
+ rb_define_method(cSSLContext, "initialize", ossl_sslctx_initialize, -1);
+ rb_define_method(cSSLContext, "ciphers", ossl_sslctx_get_ciphers, 0);
+ rb_define_method(cSSLContext, "ciphers=", ossl_sslctx_set_ciphers, 1);
+
+ /* class SSLSocket */
+ cSSLSocket = rb_define_class_under(mSSL, "SSLSocket", rb_cObject);
+ rb_define_alloc_func(cSSLSocket, ossl_ssl_s_alloc);
+ for(i = 0; i < numberof(ossl_ssl_attr_readers); i++)
+ rb_attr(cSSLSocket, rb_intern(ossl_ssl_attr_readers[i]), 1, 0, Qfalse);
+ for(i = 0; i < numberof(ossl_ssl_attrs); i++)
+ rb_attr(cSSLSocket, rb_intern(ossl_ssl_attrs[i]), 1, 1, Qfalse);
+ rb_define_alias(cSSLSocket, "to_io", "io");
+ rb_define_method(cSSLSocket, "initialize", ossl_ssl_initialize, -1);
+ rb_define_method(cSSLSocket, "connect", ossl_ssl_connect, 0);
+ rb_define_method(cSSLSocket, "accept", ossl_ssl_accept, 0);
+ rb_define_method(cSSLSocket, "sysread", ossl_ssl_read, -1);
+ rb_define_method(cSSLSocket, "syswrite", ossl_ssl_write, 1);
+ rb_define_method(cSSLSocket, "sysclose", ossl_ssl_close, 0);
+ rb_define_method(cSSLSocket, "cert", ossl_ssl_get_cert, 0);
+ rb_define_method(cSSLSocket, "peer_cert", ossl_ssl_get_peer_cert, 0);
+ rb_define_method(cSSLSocket, "peer_cert_chain", ossl_ssl_get_peer_cert_chain, 0);
+ rb_define_method(cSSLSocket, "cipher", ossl_ssl_get_cipher, 0);
+ rb_define_method(cSSLSocket, "state", ossl_ssl_get_state, 0);
+ rb_define_method(cSSLSocket, "pending", ossl_ssl_pending, 0);
+
+#define ossl_ssl_def_const(x) rb_define_const(mSSL, #x, INT2FIX(SSL_##x))
+
+ ossl_ssl_def_const(VERIFY_NONE);
+ ossl_ssl_def_const(VERIFY_PEER);
+ ossl_ssl_def_const(VERIFY_FAIL_IF_NO_PEER_CERT);
+ ossl_ssl_def_const(VERIFY_CLIENT_ONCE);
+ /* Not introduce constants included in OP_ALL such as...
+ * ossl_ssl_def_const(OP_MICROSOFT_SESS_ID_BUG);
+ * ossl_ssl_def_const(OP_NETSCAPE_CHALLENGE_BUG);
+ * ossl_ssl_def_const(OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG);
+ * ossl_ssl_def_const(OP_SSLREF2_REUSE_CERT_TYPE_BUG);
+ * ossl_ssl_def_const(OP_MICROSOFT_BIG_SSLV3_BUFFER);
+ * ossl_ssl_def_const(OP_MSIE_SSLV2_RSA_PADDING);
+ * ossl_ssl_def_const(OP_SSLEAY_080_CLIENT_DH_BUG);
+ * ossl_ssl_def_const(OP_TLS_D5_BUG);
+ * ossl_ssl_def_const(OP_TLS_BLOCK_PADDING_BUG);
+ * ossl_ssl_def_const(OP_DONT_INSERT_EMPTY_FRAGMENTS);
+ */
+ ossl_ssl_def_const(OP_ALL);
+#if defined(SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION)
+ ossl_ssl_def_const(OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
+#endif
+#if defined(SSL_OP_SINGLE_ECDH_USE)
+ ossl_ssl_def_const(OP_SINGLE_ECDH_USE);
+#endif
+ ossl_ssl_def_const(OP_SINGLE_DH_USE);
+ ossl_ssl_def_const(OP_EPHEMERAL_RSA);
+#if defined(SSL_OP_CIPHER_SERVER_PREFERENCE)
+ ossl_ssl_def_const(OP_CIPHER_SERVER_PREFERENCE);
+#endif
+ ossl_ssl_def_const(OP_TLS_ROLLBACK_BUG);
+ ossl_ssl_def_const(OP_NO_SSLv2);
+ ossl_ssl_def_const(OP_NO_SSLv3);
+ ossl_ssl_def_const(OP_NO_TLSv1);
+ ossl_ssl_def_const(OP_PKCS1_CHECK_1);
+ ossl_ssl_def_const(OP_PKCS1_CHECK_2);
+ ossl_ssl_def_const(OP_NETSCAPE_CA_DN_BUG);
+ ossl_ssl_def_const(OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG);
+}
diff --git a/ruby_1_8_5/ext/openssl/ossl_ssl.h b/ruby_1_8_5/ext/openssl/ossl_ssl.h
new file mode 100644
index 0000000000..ba9ddb1985
--- /dev/null
+++ b/ruby_1_8_5/ext/openssl/ossl_ssl.h
@@ -0,0 +1,21 @@
+/*
+ * $Id: ossl_ssl.h,v 1.1 2003/07/23 16:11:29 gotoyuzo Exp $
+ * '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 eSSLError;
+extern VALUE cSSLSocket;
+extern VALUE cSSLContext;
+
+void Init_ossl_ssl(void);
+
+#endif /* _OSSL_SSL_H_ */
diff --git a/ruby_1_8_5/ext/openssl/ossl_version.h b/ruby_1_8_5/ext/openssl/ossl_version.h
new file mode 100644
index 0000000000..6d43cdccbf
--- /dev/null
+++ b/ruby_1_8_5/ext/openssl/ossl_version.h
@@ -0,0 +1,16 @@
+/*
+ * $Id: ossl_version.h,v 1.1 2003/07/23 16:11:29 gotoyuzo Exp $
+ * '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_VERSION_H_)
+#define _OSSL_VERSION_H_
+
+#define OSSL_VERSION "1.0.0"
+
+#endif /* _OSSL_VERSION_H_ */
diff --git a/ruby_1_8_5/ext/openssl/ossl_x509.c b/ruby_1_8_5/ext/openssl/ossl_x509.c
new file mode 100644
index 0000000000..fa90e92d11
--- /dev/null
+++ b/ruby_1_8_5/ext/openssl/ossl_x509.c
@@ -0,0 +1,104 @@
+/*
+ * $Id: ossl_x509.c,v 1.2 2003/09/08 10:31:38 gotoyuzo Exp $
+ * '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'.)
+ */
+#include "ossl.h"
+
+VALUE mX509;
+
+#define DefX509Const(x) rb_define_const(mX509, #x,INT2FIX(X509_##x))
+#define DefX509Default(x,i) \
+ rb_define_const(mX509, "DEFAULT_" #x, rb_str_new2(X509_get_default_##i()))
+
+void
+Init_ossl_x509()
+{
+ mX509 = rb_define_module_under(mOSSL, "X509");
+
+ Init_ossl_x509attr();
+ Init_ossl_x509cert();
+ Init_ossl_x509crl();
+ Init_ossl_x509ext();
+ Init_ossl_x509name();
+ Init_ossl_x509req();
+ Init_ossl_x509revoked();
+ Init_ossl_x509store();
+
+ DefX509Const(V_OK);
+ DefX509Const(V_ERR_UNABLE_TO_GET_ISSUER_CERT);
+ DefX509Const(V_ERR_UNABLE_TO_GET_CRL);
+ DefX509Const(V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE);
+ DefX509Const(V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE);
+ DefX509Const(V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY);
+ DefX509Const(V_ERR_CERT_SIGNATURE_FAILURE);
+ DefX509Const(V_ERR_CRL_SIGNATURE_FAILURE);
+ DefX509Const(V_ERR_CERT_NOT_YET_VALID);
+ DefX509Const(V_ERR_CERT_HAS_EXPIRED);
+ DefX509Const(V_ERR_CRL_NOT_YET_VALID);
+ DefX509Const(V_ERR_CRL_HAS_EXPIRED);
+ DefX509Const(V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD);
+ DefX509Const(V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD);
+ DefX509Const(V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD);
+ DefX509Const(V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD);
+ DefX509Const(V_ERR_OUT_OF_MEM);
+ DefX509Const(V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT);
+ DefX509Const(V_ERR_SELF_SIGNED_CERT_IN_CHAIN);
+ DefX509Const(V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY);
+ DefX509Const(V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE);
+ DefX509Const(V_ERR_CERT_CHAIN_TOO_LONG);
+ DefX509Const(V_ERR_CERT_REVOKED);
+ DefX509Const(V_ERR_INVALID_CA);
+ DefX509Const(V_ERR_PATH_LENGTH_EXCEEDED);
+ DefX509Const(V_ERR_INVALID_PURPOSE);
+ DefX509Const(V_ERR_CERT_UNTRUSTED);
+ DefX509Const(V_ERR_CERT_REJECTED);
+ DefX509Const(V_ERR_SUBJECT_ISSUER_MISMATCH);
+ DefX509Const(V_ERR_AKID_SKID_MISMATCH);
+ DefX509Const(V_ERR_AKID_ISSUER_SERIAL_MISMATCH);
+ DefX509Const(V_ERR_KEYUSAGE_NO_CERTSIGN);
+ DefX509Const(V_ERR_APPLICATION_VERIFICATION);
+
+#if defined(X509_V_FLAG_CRL_CHECK)
+ DefX509Const(V_FLAG_CRL_CHECK);
+#endif
+#if defined(X509_V_FLAG_CRL_CHECK_ALL)
+ DefX509Const(V_FLAG_CRL_CHECK_ALL);
+#endif
+
+ DefX509Const(PURPOSE_SSL_CLIENT);
+ DefX509Const(PURPOSE_SSL_SERVER);
+ DefX509Const(PURPOSE_NS_SSL_SERVER);
+ DefX509Const(PURPOSE_SMIME_SIGN);
+ DefX509Const(PURPOSE_SMIME_ENCRYPT);
+ DefX509Const(PURPOSE_CRL_SIGN);
+ DefX509Const(PURPOSE_ANY);
+#if defined(X509_PURPOSE_OCSP_HELPER)
+ DefX509Const(PURPOSE_OCSP_HELPER);
+#endif
+
+ DefX509Const(TRUST_COMPAT);
+ DefX509Const(TRUST_SSL_CLIENT);
+ DefX509Const(TRUST_SSL_SERVER);
+ DefX509Const(TRUST_EMAIL);
+ DefX509Const(TRUST_OBJECT_SIGN);
+#if defined(X509_TRUST_OCSP_SIGN)
+ DefX509Const(TRUST_OCSP_SIGN);
+#endif
+#if defined(X509_TRUST_OCSP_REQUEST)
+ DefX509Const(TRUST_OCSP_REQUEST);
+#endif
+
+ DefX509Default(CERT_AREA, cert_area);
+ DefX509Default(CERT_DIR, cert_dir);
+ DefX509Default(CERT_FILE, cert_file);
+ DefX509Default(CERT_DIR_ENV, cert_dir_env);
+ DefX509Default(CERT_FILE_ENV, cert_file_env);
+ DefX509Default(PRIVATE_DIR, private_dir);
+}
+
diff --git a/ruby_1_8_5/ext/openssl/ossl_x509.h b/ruby_1_8_5/ext/openssl/ossl_x509.h
new file mode 100644
index 0000000000..8d1f77b302
--- /dev/null
+++ b/ruby_1_8_5/ext/openssl/ossl_x509.h
@@ -0,0 +1,114 @@
+/*
+ * $Id: ossl_x509.h,v 1.2 2003/11/01 09:24:55 gotoyuzo Exp $
+ * '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_X509_H_)
+#define _OSSL_X509_H_
+
+/*
+ * X509 main module
+ */
+extern VALUE mX509;
+
+void Init_ossl_x509(void);
+
+/*
+ * X509Attr
+ */
+extern VALUE cX509Attr;
+extern VALUE eX509AttrError;
+
+VALUE ossl_x509attr_new(X509_ATTRIBUTE *);
+X509_ATTRIBUTE *DupX509AttrPtr(VALUE);
+void Init_ossl_x509attr(void);
+
+/*
+ * X509Cert
+ */
+extern VALUE cX509Cert;
+extern VALUE eX509CertError;
+
+VALUE ossl_x509_new(X509 *);
+VALUE ossl_x509_new_from_file(VALUE);
+X509 *GetX509CertPtr(VALUE);
+X509 *DupX509CertPtr(VALUE);
+void Init_ossl_x509cert(void);
+
+/*
+ * X509CRL
+ */
+extern VALUE cX509CRL;
+extern VALUE eX509CRLError;
+
+VALUE ossl_x509crl_new(X509_CRL *);
+X509_CRL *GetX509CRLPtr(VALUE);
+X509_CRL *DupX509CRLPtr(VALUE);
+void Init_ossl_x509crl(void);
+
+/*
+ * X509Extension
+ */
+extern VALUE cX509Ext;
+extern VALUE cX509ExtFactory;
+extern VALUE eX509ExtError;
+
+VALUE ossl_x509ext_new(X509_EXTENSION *);
+X509_EXTENSION *GetX509ExtPtr(VALUE);
+X509_EXTENSION *DupX509ExtPtr(VALUE);
+void Init_ossl_x509ext(void);
+
+/*
+ * X509Name
+ */
+extern VALUE cX509Name;
+extern VALUE eX509NameError;
+
+VALUE ossl_x509name_new(X509_NAME *);
+X509_NAME *GetX509NamePtr(VALUE);
+void Init_ossl_x509name(void);
+
+/*
+ * X509Request
+ */
+extern VALUE cX509Req;
+extern VALUE eX509ReqError;
+
+VALUE ossl_x509req_new(X509_REQ *);
+X509_REQ *GetX509ReqPtr(VALUE);
+X509_REQ *DupX509ReqPtr(VALUE);
+void Init_ossl_x509req(void);
+
+/*
+ * X509Revoked
+ */
+extern VALUE cX509Rev;
+extern VALUE eX509RevError;
+
+VALUE ossl_x509revoked_new(X509_REVOKED *);
+X509_REVOKED *DupX509RevokedPtr(VALUE);
+void Init_ossl_x509revoked(void);
+
+/*
+ * X509Store and X509StoreContext
+ */
+extern VALUE cX509Store;
+extern VALUE cX509StoreContext;
+extern VALUE eX509StoreError;
+
+VALUE ossl_x509store_new(X509_STORE *);
+X509_STORE *GetX509StorePtr(VALUE);
+X509_STORE *DupX509StorePtr(VALUE);
+
+VALUE ossl_x509stctx_new(X509_STORE_CTX *);
+VALUE ossl_x509stctx_clear_ptr(VALUE);
+X509_STORE_CTX *GetX509StCtxtPtr(VALUE);
+
+void Init_ossl_x509store(void);
+
+#endif /* _OSSL_X509_H_ */
diff --git a/ruby_1_8_5/ext/openssl/ossl_x509attr.c b/ruby_1_8_5/ext/openssl/ossl_x509attr.c
new file mode 100644
index 0000000000..91a0795209
--- /dev/null
+++ b/ruby_1_8_5/ext/openssl/ossl_x509attr.c
@@ -0,0 +1,249 @@
+/*
+ * $Id: ossl_x509attr.c,v 1.4.2.2 2004/12/15 01:54:38 matz Exp $
+ * 'OpenSSL for Ruby' project
+ * Copyright (C) 2001 Michal Rokos <m.rokos@sh.cvut.cz>
+ * All rights reserved.
+ */
+/*
+ * This program is licenced under the same licence as Ruby.
+ * (See the file 'LICENCE'.)
+ */
+#include "ossl.h"
+
+#define WrapX509Attr(klass, obj, attr) do { \
+ if (!attr) { \
+ ossl_raise(rb_eRuntimeError, "ATTR wasn't initialized!"); \
+ } \
+ obj = Data_Wrap_Struct(klass, 0, X509_ATTRIBUTE_free, attr); \
+} while (0)
+#define GetX509Attr(obj, attr) do { \
+ Data_Get_Struct(obj, X509_ATTRIBUTE, attr); \
+ if (!attr) { \
+ ossl_raise(rb_eRuntimeError, "ATTR wasn't initialized!"); \
+ } \
+} while (0)
+#define SafeGetX509Attr(obj, attr) do { \
+ OSSL_Check_Kind(obj, cX509Attr); \
+ GetX509Attr(obj, attr); \
+} while (0)
+
+/*
+ * Classes
+ */
+VALUE cX509Attr;
+VALUE eX509AttrError;
+
+/*
+ * Public
+ */
+VALUE
+ossl_x509attr_new(X509_ATTRIBUTE *attr)
+{
+ X509_ATTRIBUTE *new;
+ VALUE obj;
+
+ if (!attr) {
+ new = X509_ATTRIBUTE_new();
+ } else {
+ new = X509_ATTRIBUTE_dup(attr);
+ }
+ if (!new) {
+ ossl_raise(eX509AttrError, NULL);
+ }
+ WrapX509Attr(cX509Attr, obj, new);
+
+ return obj;
+}
+
+X509_ATTRIBUTE *
+DupX509AttrPtr(VALUE obj)
+{
+ X509_ATTRIBUTE *attr, *new;
+
+ SafeGetX509Attr(obj, attr);
+ if (!(new = X509_ATTRIBUTE_dup(attr))) {
+ ossl_raise(eX509AttrError, NULL);
+ }
+
+ return new;
+}
+
+/*
+ * Private
+ */
+static VALUE
+ossl_x509attr_alloc(VALUE klass)
+{
+ X509_ATTRIBUTE *attr;
+ VALUE obj;
+
+ if (!(attr = X509_ATTRIBUTE_new()))
+ ossl_raise(eX509AttrError, NULL);
+ WrapX509Attr(klass, obj, attr);
+
+ return obj;
+}
+
+static VALUE
+ossl_x509attr_initialize(int argc, VALUE *argv, VALUE self)
+{
+ VALUE oid, value;
+ X509_ATTRIBUTE *attr;
+ unsigned char *p;
+
+ GetX509Attr(self, attr);
+ if(rb_scan_args(argc, argv, "11", &oid, &value) == 1){
+ oid = ossl_to_der_if_possible(oid);
+ StringValue(oid);
+ p = RSTRING(oid)->ptr;
+ if(!d2i_X509_ATTRIBUTE((X509_ATTRIBUTE**)&DATA_PTR(self),
+ &p, RSTRING(oid)->len)){
+ ossl_raise(eX509AttrError, NULL);
+ }
+ return self;
+ }
+ 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;
+
+ s = StringValuePtr(oid);
+ obj = OBJ_txt2obj(s, 0);
+ if(!obj) obj = OBJ_txt2obj(s, 1);
+ if(!obj) ossl_raise(eX509AttrError, NULL);
+ GetX509Attr(self, attr);
+ 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;
+
+ 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)
+{
+ X509_ATTRIBUTE *attr;
+ ASN1_TYPE *a1type;
+
+ if(!(a1type = ossl_asn1_get_asn1type(value)))
+ ossl_raise(eASN1Error, "could not get ASN1_TYPE");
+ if(ASN1_TYPE_get(a1type) == V_ASN1_SEQUENCE){
+ ASN1_TYPE_free(a1type);
+ ossl_raise(eASN1Error, "couldn't set SEQUENCE for attribute value.");
+ }
+ GetX509Attr(self, attr);
+ if(attr->value.set){
+ if(OSSL_X509ATTR_IS_SINGLE(attr)) ASN1_TYPE_free(attr->value.single);
+ else sk_ASN1_TYPE_free(attr->value.set);
+ }
+ OSSL_X509ATTR_SET_SINGLE(attr);
+ attr->value.single = a1type;
+
+ return value;
+}
+
+static VALUE
+ossl_x509attr_get_value(VALUE self)
+{
+ X509_ATTRIBUTE *attr;
+ VALUE str, asn1;
+ long length;
+ unsigned char *p;
+
+ GetX509Attr(self, attr);
+ if(attr->value.ptr == NULL) return Qnil;
+ if(OSSL_X509ATTR_IS_SINGLE(attr)){
+ length = i2d_ASN1_TYPE(attr->value.single, NULL);
+ str = rb_str_new(0, length);
+ p = RSTRING(str)->ptr;
+ i2d_ASN1_TYPE(attr->value.single, &p);
+ ossl_str_adjust(str, p);
+ }
+ else{
+ length = i2d_ASN1_SET_OF_ASN1_TYPE(attr->value.set, NULL,
+ i2d_ASN1_TYPE, V_ASN1_SET, V_ASN1_UNIVERSAL, 0);
+ str = rb_str_new(0, length);
+ p = RSTRING(str)->ptr;
+ i2d_ASN1_SET_OF_ASN1_TYPE(attr->value.set, &p,
+ i2d_ASN1_TYPE, V_ASN1_SET, V_ASN1_UNIVERSAL, 0);
+ ossl_str_adjust(str, p);
+ }
+ asn1 = rb_funcall(mASN1, rb_intern("decode"), 1, str);
+
+ return asn1;
+}
+
+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
+ */
+void
+Init_ossl_x509attr()
+{
+ eX509AttrError = rb_define_class_under(mX509, "AttributeError", eOSSLError);
+
+ cX509Attr = rb_define_class_under(mX509, "Attribute", rb_cObject);
+ 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/ruby_1_8_5/ext/openssl/ossl_x509cert.c b/ruby_1_8_5/ext/openssl/ossl_x509cert.c
new file mode 100644
index 0000000000..3ac9c894da
--- /dev/null
+++ b/ruby_1_8_5/ext/openssl/ossl_x509cert.c
@@ -0,0 +1,671 @@
+/*
+ * $Id: ossl_x509cert.c,v 1.3.2.1 2004/12/15 01:54:38 matz Exp $
+ * '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'.)
+ */
+#include "ossl.h"
+
+#define WrapX509(klass, obj, x509) do { \
+ if (!x509) { \
+ ossl_raise(rb_eRuntimeError, "CERT wasn't initialized!"); \
+ } \
+ obj = Data_Wrap_Struct(klass, 0, X509_free, x509); \
+} while (0)
+#define GetX509(obj, x509) do { \
+ Data_Get_Struct(obj, X509, x509); \
+ if (!x509) { \
+ ossl_raise(rb_eRuntimeError, "CERT wasn't initialized!"); \
+ } \
+} while (0)
+#define SafeGetX509(obj, x509) do { \
+ OSSL_Check_Kind(obj, cX509Cert); \
+ GetX509(obj, x509); \
+} while (0)
+
+/*
+ * Classes
+ */
+VALUE cX509Cert;
+VALUE eX509CertError;
+
+/*
+ * Public
+ */
+VALUE
+ossl_x509_new(X509 *x509)
+{
+ X509 *new;
+ VALUE obj;
+
+ if (!x509) {
+ new = X509_new();
+ } else {
+ new = X509_dup(x509);
+ }
+ if (!new) {
+ ossl_raise(eX509CertError, NULL);
+ }
+ WrapX509(cX509Cert, obj, new);
+
+ return obj;
+}
+
+VALUE
+ossl_x509_new_from_file(VALUE filename)
+{
+ X509 *x509;
+ FILE *fp;
+ VALUE obj;
+
+ SafeStringValue(filename);
+ if (!(fp = fopen(RSTRING(filename)->ptr, "r"))) {
+ ossl_raise(eX509CertError, "%s", strerror(errno));
+ }
+ x509 = PEM_read_X509(fp, NULL, NULL, NULL);
+ /*
+ * prepare for DER...
+#if !defined(OPENSSL_NO_FP_API)
+ if (!x509) {
+ rewind(fp);
+
+ x509 = d2i_X509_fp(fp, NULL);
+ }
+#endif
+ */
+ fclose(fp);
+ if (!x509) {
+ ossl_raise(eX509CertError, NULL);
+ }
+ WrapX509(cX509Cert, obj, x509);
+
+ return obj;
+}
+
+X509 *
+GetX509CertPtr(VALUE obj)
+{
+ X509 *x509;
+
+ SafeGetX509(obj, x509);
+
+ return x509;
+}
+
+X509 *
+DupX509CertPtr(VALUE obj)
+{
+ X509 *x509;
+
+ SafeGetX509(obj, x509);
+
+ CRYPTO_add(&x509->references, 1, CRYPTO_LOCK_X509);
+
+ return x509;
+}
+
+/*
+ * Private
+ */
+static VALUE
+ossl_x509_alloc(VALUE klass)
+{
+ X509 *x509;
+ VALUE obj;
+
+ x509 = X509_new();
+ if (!x509) ossl_raise(eX509CertError, NULL);
+
+ WrapX509(klass, obj, x509);
+
+ return obj;
+}
+
+static VALUE
+ossl_x509_initialize(int argc, VALUE *argv, VALUE self)
+{
+ BIO *in;
+ X509 *x509;
+ VALUE arg;
+
+ if (rb_scan_args(argc, argv, "01", &arg) == 0) {
+ /* create just empty X509Cert */
+ return self;
+ }
+ arg = ossl_to_der_if_possible(arg);
+ in = ossl_obj2bio(arg);
+ x509 = PEM_read_bio_X509(in, (X509 **)&DATA_PTR(self), NULL, NULL);
+ if (!x509) {
+ BIO_reset(in);
+ x509 = d2i_X509_bio(in, (X509 **)&DATA_PTR(self));
+ }
+ BIO_free(in);
+ if (!x509) ossl_raise(eX509CertError, NULL);
+
+ return self;
+}
+
+static VALUE
+ossl_x509_copy(VALUE self, VALUE other)
+{
+ X509 *a, *b, *x509;
+
+ rb_check_frozen(self);
+ if (self == other) return self;
+
+ GetX509(self, a);
+ SafeGetX509(other, b);
+
+ x509 = X509_dup(b);
+ if (!x509) ossl_raise(eX509CertError, NULL);
+
+ DATA_PTR(self) = x509;
+ X509_free(a);
+
+ return self;
+}
+
+static VALUE
+ossl_x509_to_der(VALUE self)
+{
+ X509 *x509;
+ VALUE str;
+ long len;
+ unsigned char *p;
+
+ GetX509(self, x509);
+ if ((len = i2d_X509(x509, NULL)) <= 0)
+ ossl_raise(eX509CertError, NULL);
+ 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;
+}
+
+static VALUE
+ossl_x509_to_pem(VALUE self)
+{
+ X509 *x509;
+ BIO *out;
+ VALUE str;
+
+ GetX509(self, x509);
+ out = BIO_new(BIO_s_mem());
+ if (!out) ossl_raise(eX509CertError, NULL);
+
+ if (!PEM_write_bio_X509(out, x509)) {
+ BIO_free(out);
+ ossl_raise(eX509CertError, NULL);
+ }
+ str = ossl_membio2str(out);
+
+ return str;
+}
+
+static VALUE
+ossl_x509_to_text(VALUE self)
+{
+ X509 *x509;
+ BIO *out;
+ VALUE str;
+
+ GetX509(self, x509);
+
+ out = BIO_new(BIO_s_mem());
+ if (!out) ossl_raise(eX509CertError, NULL);
+
+ if (!X509_print(out, x509)) {
+ BIO_free(out);
+ ossl_raise(eX509CertError, NULL);
+ }
+ str = ossl_membio2str(out);
+
+ return str;
+}
+
+#if 0
+/*
+ * Makes from X509 X509_REQuest
+ */
+static VALUE
+ossl_x509_to_req(VALUE self)
+{
+ X509 *x509;
+ X509_REQ *req;
+ VALUE obj;
+
+ GetX509(self, x509);
+ if (!(req = X509_to_X509_REQ(x509, NULL, EVP_md5()))) {
+ ossl_raise(eX509CertError, NULL);
+ }
+ obj = ossl_x509req_new(req);
+ X509_REQ_free(req);
+
+ return obj;
+}
+#endif
+
+static VALUE
+ossl_x509_get_version(VALUE self)
+{
+ X509 *x509;
+
+ GetX509(self, x509);
+
+ return LONG2NUM(X509_get_version(x509));
+}
+
+static VALUE
+ossl_x509_set_version(VALUE self, VALUE version)
+{
+ X509 *x509;
+ long ver;
+
+ if ((ver = NUM2LONG(version)) < 0) {
+ ossl_raise(eX509CertError, "version must be >= 0!");
+ }
+ GetX509(self, x509);
+ if (!X509_set_version(x509, ver)) {
+ ossl_raise(eX509CertError, NULL);
+ }
+
+ return version;
+}
+
+static VALUE
+ossl_x509_get_serial(VALUE self)
+{
+ X509 *x509;
+
+ GetX509(self, x509);
+
+ return asn1integer_to_num(X509_get_serialNumber(x509));
+}
+
+static VALUE
+ossl_x509_set_serial(VALUE self, VALUE num)
+{
+ X509 *x509;
+
+ GetX509(self, x509);
+
+ x509->cert_info->serialNumber =
+ num_to_asn1integer(num, X509_get_serialNumber(x509));
+
+ return num;
+}
+
+static VALUE
+ossl_x509_get_signature_algorithm(VALUE self)
+{
+ X509 *x509;
+ BIO *out;
+ VALUE str;
+
+ GetX509(self, x509);
+ out = BIO_new(BIO_s_mem());
+ if (!out) ossl_raise(eX509CertError, NULL);
+
+ if (!i2a_ASN1_OBJECT(out, x509->cert_info->signature->algorithm)) {
+ BIO_free(out);
+ ossl_raise(eX509CertError, NULL);
+ }
+ str = ossl_membio2str(out);
+
+ return str;
+}
+
+static VALUE
+ossl_x509_get_subject(VALUE self)
+{
+ X509 *x509;
+ X509_NAME *name;
+
+ GetX509(self, x509);
+ if (!(name = X509_get_subject_name(x509))) { /* NO DUP - don't free! */
+ ossl_raise(eX509CertError, NULL);
+ }
+
+ return ossl_x509name_new(name);
+}
+
+static VALUE
+ossl_x509_set_subject(VALUE self, VALUE subject)
+{
+ X509 *x509;
+
+ GetX509(self, x509);
+ if (!X509_set_subject_name(x509, GetX509NamePtr(subject))) { /* DUPs name */
+ ossl_raise(eX509CertError, NULL);
+ }
+
+ return subject;
+}
+
+static VALUE
+ossl_x509_get_issuer(VALUE self)
+{
+ X509 *x509;
+ X509_NAME *name;
+
+ GetX509(self, x509);
+ if(!(name = X509_get_issuer_name(x509))) { /* NO DUP - don't free! */
+ ossl_raise(eX509CertError, NULL);
+ }
+
+ return ossl_x509name_new(name);
+}
+
+static VALUE
+ossl_x509_set_issuer(VALUE self, VALUE issuer)
+{
+ X509 *x509;
+
+ GetX509(self, x509);
+ if (!X509_set_issuer_name(x509, GetX509NamePtr(issuer))) { /* DUPs name */
+ ossl_raise(eX509CertError, NULL);
+ }
+
+ return issuer;
+}
+
+static VALUE
+ossl_x509_get_not_before(VALUE self)
+{
+ X509 *x509;
+ ASN1_UTCTIME *asn1time;
+
+ GetX509(self, x509);
+ if (!(asn1time = X509_get_notBefore(x509))) { /* NO DUP - don't free! */
+ ossl_raise(eX509CertError, NULL);
+ }
+
+ return asn1time_to_time(asn1time);
+}
+
+static VALUE
+ossl_x509_set_not_before(VALUE self, VALUE time)
+{
+ X509 *x509;
+ time_t sec;
+
+ sec = time_to_time_t(time);
+ GetX509(self, x509);
+ if (!X509_time_adj(X509_get_notBefore(x509), 0, &sec)) {
+ ossl_raise(eX509CertError, NULL);
+ }
+
+ return time;
+}
+
+static VALUE
+ossl_x509_get_not_after(VALUE self)
+{
+ X509 *x509;
+ ASN1_TIME *asn1time;
+
+ GetX509(self, x509);
+ if (!(asn1time = X509_get_notAfter(x509))) { /* NO DUP - don't free! */
+ ossl_raise(eX509CertError, NULL);
+ }
+
+ return asn1time_to_time(asn1time);
+}
+
+static VALUE
+ossl_x509_set_not_after(VALUE self, VALUE time)
+{
+ X509 *x509;
+ time_t sec;
+
+ sec = time_to_time_t(time);
+ GetX509(self, x509);
+ if (!X509_time_adj(X509_get_notAfter(x509), 0, &sec)) {
+ ossl_raise(eX509CertError, NULL);
+ }
+
+ return time;
+}
+
+static VALUE
+ossl_x509_get_public_key(VALUE self)
+{
+ X509 *x509;
+ EVP_PKEY *pkey;
+
+ GetX509(self, x509);
+ if (!(pkey = X509_get_pubkey(x509))) { /* adds an reference */
+ ossl_raise(eX509CertError, NULL);
+ }
+
+ return ossl_pkey_new(pkey); /* NO DUP - OK */
+}
+
+static VALUE
+ossl_x509_set_public_key(VALUE self, VALUE key)
+{
+ X509 *x509;
+
+ GetX509(self, x509);
+ if (!X509_set_pubkey(x509, GetPKeyPtr(key))) { /* DUPs pkey */
+ ossl_raise(eX509CertError, NULL);
+ }
+
+ return key;
+}
+
+static VALUE
+ossl_x509_sign(VALUE self, VALUE key, VALUE digest)
+{
+ X509 *x509;
+ EVP_PKEY *pkey;
+ const EVP_MD *md;
+
+ pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */
+ md = GetDigestPtr(digest);
+ GetX509(self, x509);
+ if (!X509_sign(x509, pkey, md)) {
+ ossl_raise(eX509CertError, NULL);
+ }
+
+ return self;
+}
+
+/*
+ * Checks that cert signature is made with PRIVversion of this PUBLIC 'key'
+ */
+static VALUE
+ossl_x509_verify(VALUE self, VALUE key)
+{
+ X509 *x509;
+ EVP_PKEY *pkey;
+ int i;
+
+ pkey = GetPKeyPtr(key); /* NO NEED TO DUP */
+ GetX509(self, x509);
+ if ((i = X509_verify(x509, pkey)) < 0) {
+ ossl_raise(eX509CertError, NULL);
+ }
+ if (i > 0) {
+ return Qtrue;
+ }
+
+ return Qfalse;
+}
+
+/*
+ * Checks if 'key' is PRIV key for this cert
+ */
+static VALUE
+ossl_x509_check_private_key(VALUE self, VALUE key)
+{
+ X509 *x509;
+ EVP_PKEY *pkey;
+
+ /* not needed private key, but should be */
+ pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */
+ GetX509(self, x509);
+ if (!X509_check_private_key(x509, pkey)) {
+ OSSL_Warning("Check private key:%s", OSSL_ErrMsg());
+ return Qfalse;
+ }
+
+ return Qtrue;
+}
+
+/*
+ * Gets X509v3 extensions as array of X509Ext objects
+ */
+static VALUE
+ossl_x509_get_extensions(VALUE self)
+{
+ X509 *x509;
+ int count, i;
+ X509_EXTENSION *ext;
+ VALUE ary;
+
+ GetX509(self, x509);
+ count = X509_get_ext_count(x509);
+ if (count < 0) {
+ return rb_ary_new();
+ }
+ ary = rb_ary_new2(count);
+ for (i=0; i<count; i++) {
+ ext = X509_get_ext(x509, i); /* NO DUP - don't free! */
+ rb_ary_push(ary, ossl_x509ext_new(ext));
+ }
+
+ return ary;
+}
+
+/*
+ * Sets X509_EXTENSIONs
+ */
+static VALUE
+ossl_x509_set_extensions(VALUE self, VALUE ary)
+{
+ X509 *x509;
+ X509_EXTENSION *ext;
+ int i;
+
+ Check_Type(ary, T_ARRAY);
+ /* All ary's members should be X509Extension */
+ for (i=0; i<RARRAY(ary)->len; i++) {
+ OSSL_Check_Kind(RARRAY(ary)->ptr[i], cX509Ext);
+ }
+ GetX509(self, x509);
+ sk_X509_EXTENSION_pop_free(x509->cert_info->extensions, X509_EXTENSION_free);
+ x509->cert_info->extensions = NULL;
+ for (i=0; i<RARRAY(ary)->len; i++) {
+ ext = DupX509ExtPtr(RARRAY(ary)->ptr[i]);
+
+ if (!X509_add_ext(x509, ext, -1)) { /* DUPs ext - FREE it */
+ X509_EXTENSION_free(ext);
+ ossl_raise(eX509CertError, NULL);
+ }
+ X509_EXTENSION_free(ext);
+ }
+
+ return ary;
+}
+
+static VALUE
+ossl_x509_add_extension(VALUE self, VALUE extension)
+{
+ X509 *x509;
+ X509_EXTENSION *ext;
+
+ GetX509(self, x509);
+ ext = DupX509ExtPtr(extension);
+ if (!X509_add_ext(x509, ext, -1)) { /* DUPs ext - FREE it */
+ X509_EXTENSION_free(ext);
+ ossl_raise(eX509CertError, NULL);
+ }
+ X509_EXTENSION_free(ext);
+
+ return extension;
+}
+
+static VALUE
+ossl_x509_inspect(VALUE self)
+{
+ VALUE str;
+ char *cname = rb_class2name(rb_obj_class(self));
+
+ str = rb_str_new2("#<");
+ rb_str_cat2(str, cname);
+ rb_str_cat2(str, " ");
+
+ rb_str_cat2(str, "subject=");
+ rb_str_append(str, rb_inspect(ossl_x509_get_subject(self)));
+ rb_str_cat2(str, ", ");
+
+ rb_str_cat2(str, "issuer=");
+ rb_str_append(str, rb_inspect(ossl_x509_get_issuer(self)));
+ rb_str_cat2(str, ", ");
+
+ rb_str_cat2(str, "serial=");
+ rb_str_append(str, rb_inspect(ossl_x509_get_serial(self)));
+ rb_str_cat2(str, ", ");
+
+ rb_str_cat2(str, "not_before=");
+ rb_str_append(str, rb_inspect(ossl_x509_get_not_before(self)));
+ rb_str_cat2(str, ", ");
+
+ rb_str_cat2(str, "not_after=");
+ rb_str_append(str, rb_inspect(ossl_x509_get_not_after(self)));
+
+ str = rb_str_cat2(str, ">");
+
+ return str;
+}
+
+/*
+ * INIT
+ */
+void
+Init_ossl_x509cert()
+{
+ eX509CertError = rb_define_class_under(mX509, "CertificateError", eOSSLError);
+
+ cX509Cert = rb_define_class_under(mX509, "Certificate", rb_cObject);
+
+ rb_define_alloc_func(cX509Cert, ossl_x509_alloc);
+ rb_define_method(cX509Cert, "initialize", ossl_x509_initialize, -1);
+ rb_define_copy_func(cX509Cert, ossl_x509_copy);
+
+ rb_define_method(cX509Cert, "to_der", ossl_x509_to_der, 0);
+ rb_define_method(cX509Cert, "to_pem", ossl_x509_to_pem, 0);
+ rb_define_alias(cX509Cert, "to_s", "to_pem");
+ rb_define_method(cX509Cert, "to_text", ossl_x509_to_text, 0);
+ rb_define_method(cX509Cert, "version", ossl_x509_get_version, 0);
+ rb_define_method(cX509Cert, "version=", ossl_x509_set_version, 1);
+ rb_define_method(cX509Cert, "signature_algorithm", ossl_x509_get_signature_algorithm, 0);
+ rb_define_method(cX509Cert, "serial", ossl_x509_get_serial, 0);
+ rb_define_method(cX509Cert, "serial=", ossl_x509_set_serial, 1);
+ rb_define_method(cX509Cert, "subject", ossl_x509_get_subject, 0);
+ rb_define_method(cX509Cert, "subject=", ossl_x509_set_subject, 1);
+ rb_define_method(cX509Cert, "issuer", ossl_x509_get_issuer, 0);
+ rb_define_method(cX509Cert, "issuer=", ossl_x509_set_issuer, 1);
+ rb_define_method(cX509Cert, "not_before", ossl_x509_get_not_before, 0);
+ rb_define_method(cX509Cert, "not_before=", ossl_x509_set_not_before, 1);
+ rb_define_method(cX509Cert, "not_after", ossl_x509_get_not_after, 0);
+ rb_define_method(cX509Cert, "not_after=", ossl_x509_set_not_after, 1);
+ rb_define_method(cX509Cert, "public_key", ossl_x509_get_public_key, 0);
+ rb_define_method(cX509Cert, "public_key=", ossl_x509_set_public_key, 1);
+ rb_define_method(cX509Cert, "sign", ossl_x509_sign, 2);
+ rb_define_method(cX509Cert, "verify", ossl_x509_verify, 1);
+ rb_define_method(cX509Cert, "check_private_key", ossl_x509_check_private_key, 1);
+ rb_define_method(cX509Cert, "extensions", ossl_x509_get_extensions, 0);
+ rb_define_method(cX509Cert, "extensions=", ossl_x509_set_extensions, 1);
+ rb_define_method(cX509Cert, "add_extension", ossl_x509_add_extension, 1);
+ rb_define_method(cX509Cert, "inspect", ossl_x509_inspect, 0);
+}
+
diff --git a/ruby_1_8_5/ext/openssl/ossl_x509crl.c b/ruby_1_8_5/ext/openssl/ossl_x509crl.c
new file mode 100644
index 0000000000..62d27fe7a4
--- /dev/null
+++ b/ruby_1_8_5/ext/openssl/ossl_x509crl.c
@@ -0,0 +1,535 @@
+/*
+ * $Id: ossl_x509crl.c,v 1.3.2.1 2004/12/15 01:54:38 matz Exp $
+ * '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'.)
+ */
+#include "ossl.h"
+
+#define WrapX509CRL(klass, obj, crl) do { \
+ if (!crl) { \
+ ossl_raise(rb_eRuntimeError, "CRL wasn't initialized!"); \
+ } \
+ obj = Data_Wrap_Struct(klass, 0, X509_CRL_free, crl); \
+} while (0)
+#define GetX509CRL(obj, crl) do { \
+ Data_Get_Struct(obj, X509_CRL, crl); \
+ if (!crl) { \
+ ossl_raise(rb_eRuntimeError, "CRL wasn't initialized!"); \
+ } \
+} while (0)
+#define SafeGetX509CRL(obj, crl) do { \
+ OSSL_Check_Kind(obj, cX509CRL); \
+ GetX509CRL(obj, crl); \
+} while (0)
+
+/*
+ * Classes
+ */
+VALUE cX509CRL;
+VALUE eX509CRLError;
+
+/*
+ * PUBLIC
+ */
+X509_CRL *
+GetX509CRLPtr(VALUE obj)
+{
+ X509_CRL *crl;
+
+ SafeGetX509CRL(obj, crl);
+
+ return crl;
+}
+
+X509_CRL *
+DupX509CRLPtr(VALUE obj)
+{
+ X509_CRL *crl;
+
+ SafeGetX509CRL(obj, crl);
+ CRYPTO_add(&crl->references, 1, CRYPTO_LOCK_X509_CRL);
+
+ return crl;
+}
+
+VALUE
+ossl_x509crl_new(X509_CRL *crl)
+{
+ X509_CRL *tmp;
+ VALUE obj;
+
+ tmp = crl ? X509_CRL_dup(crl) : X509_CRL_new();
+ if(!tmp) ossl_raise(eX509CRLError, NULL);
+ WrapX509CRL(cX509CRL, obj, tmp);
+
+ return obj;
+}
+
+/*
+ * PRIVATE
+ */
+static VALUE
+ossl_x509crl_alloc(VALUE klass)
+{
+ X509_CRL *crl;
+ VALUE obj;
+
+ if (!(crl = X509_CRL_new())) {
+ ossl_raise(eX509CRLError, NULL);
+ }
+ WrapX509CRL(klass, obj, crl);
+
+ return obj;
+}
+
+static VALUE
+ossl_x509crl_initialize(int argc, VALUE *argv, VALUE self)
+{
+ BIO *in;
+ X509_CRL *crl;
+ VALUE arg;
+
+ if (rb_scan_args(argc, argv, "01", &arg) == 0) {
+ return 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));
+ }
+ BIO_free(in);
+ if (!crl) ossl_raise(eX509CRLError, NULL);
+
+ return self;
+}
+
+static VALUE
+ossl_x509crl_copy(VALUE self, VALUE other)
+{
+ X509_CRL *a, *b, *crl;
+
+ rb_check_frozen(self);
+ if (self == other) return self;
+ GetX509CRL(self, a);
+ SafeGetX509CRL(other, b);
+ if (!(crl = X509_CRL_dup(b))) {
+ ossl_raise(eX509CRLError, NULL);
+ }
+ X509_CRL_free(a);
+ DATA_PTR(self) = crl;
+
+ return self;
+}
+
+static VALUE
+ossl_x509crl_get_version(VALUE self)
+{
+ X509_CRL *crl;
+ long ver;
+
+ GetX509CRL(self, crl);
+ ver = X509_CRL_get_version(crl);
+
+ return LONG2NUM(ver);
+}
+
+static VALUE
+ossl_x509crl_set_version(VALUE self, VALUE version)
+{
+ X509_CRL *crl;
+ long ver;
+
+ if ((ver = NUM2LONG(version)) < 0) {
+ ossl_raise(eX509CRLError, "version must be >= 0!");
+ }
+ GetX509CRL(self, crl);
+ if (!X509_CRL_set_version(crl, ver)) {
+ ossl_raise(eX509CRLError, NULL);
+ }
+
+ return version;
+}
+
+static VALUE
+ossl_x509crl_get_signature_algorithm(VALUE self)
+{
+ X509_CRL *crl;
+ BIO *out;
+ BUF_MEM *buf;
+ VALUE str;
+
+ GetX509CRL(self, crl);
+ if (!(out = BIO_new(BIO_s_mem()))) {
+ ossl_raise(eX509CRLError, NULL);
+ }
+ if (!i2a_ASN1_OBJECT(out, crl->sig_alg->algorithm)) {
+ BIO_free(out);
+ ossl_raise(eX509CRLError, NULL);
+ }
+ BIO_get_mem_ptr(out, &buf);
+ str = rb_str_new(buf->data, buf->length);
+ BIO_free(out);
+ return str;
+}
+
+static VALUE
+ossl_x509crl_get_issuer(VALUE self)
+{
+ X509_CRL *crl;
+
+ GetX509CRL(self, crl);
+
+ return ossl_x509name_new(X509_CRL_get_issuer(crl)); /* NO DUP - don't free */
+}
+
+static VALUE
+ossl_x509crl_set_issuer(VALUE self, VALUE issuer)
+{
+ X509_CRL *crl;
+
+ GetX509CRL(self, crl);
+
+ if (!X509_CRL_set_issuer_name(crl, GetX509NamePtr(issuer))) { /* DUPs name */
+ ossl_raise(eX509CRLError, NULL);
+ }
+ return issuer;
+}
+
+static VALUE
+ossl_x509crl_get_last_update(VALUE self)
+{
+ X509_CRL *crl;
+
+ GetX509CRL(self, crl);
+
+ return asn1time_to_time(X509_CRL_get_lastUpdate(crl));
+}
+
+static VALUE
+ossl_x509crl_set_last_update(VALUE self, VALUE time)
+{
+ X509_CRL *crl;
+ time_t sec;
+
+ sec = time_to_time_t(time);
+ GetX509CRL(self, crl);
+ if (!X509_time_adj(crl->crl->lastUpdate, 0, &sec)) {
+ ossl_raise(eX509CRLError, NULL);
+ }
+
+ return time;
+}
+
+static VALUE
+ossl_x509crl_get_next_update(VALUE self)
+{
+ X509_CRL *crl;
+
+ GetX509CRL(self, crl);
+
+ return asn1time_to_time(X509_CRL_get_nextUpdate(crl));
+}
+
+static VALUE
+ossl_x509crl_set_next_update(VALUE self, VALUE time)
+{
+ X509_CRL *crl;
+ time_t sec;
+
+ sec = time_to_time_t(time);
+ GetX509CRL(self, crl);
+ /* This must be some thinko in OpenSSL */
+ if (!(crl->crl->nextUpdate = X509_time_adj(crl->crl->nextUpdate, 0, &sec))){
+ ossl_raise(eX509CRLError, NULL);
+ }
+
+ return time;
+}
+
+static VALUE
+ossl_x509crl_get_revoked(VALUE self)
+{
+ X509_CRL *crl;
+ int i, num;
+ X509_REVOKED *rev;
+ VALUE ary, revoked;
+
+ GetX509CRL(self, crl);
+ num = sk_X509_CRL_num(X509_CRL_get_REVOKED(crl));
+ if (num < 0) {
+ OSSL_Debug("num < 0???");
+ return rb_ary_new();
+ }
+ ary = rb_ary_new2(num);
+ for(i=0; i<num; i++) {
+ /* NO DUP - don't free! */
+ rev = (X509_REVOKED *)sk_X509_CRL_value(X509_CRL_get_REVOKED(crl), i);
+ revoked = ossl_x509revoked_new(rev);
+ rb_ary_push(ary, revoked);
+ }
+
+ return ary;
+}
+
+static VALUE
+ossl_x509crl_set_revoked(VALUE self, VALUE ary)
+{
+ X509_CRL *crl;
+ X509_REVOKED *rev;
+ int i;
+
+ Check_Type(ary, T_ARRAY);
+ /* All ary members should be X509 Revoked */
+ for (i=0; i<RARRAY(ary)->len; i++) {
+ OSSL_Check_Kind(RARRAY(ary)->ptr[i], cX509Rev);
+ }
+ GetX509CRL(self, crl);
+ sk_X509_REVOKED_pop_free(crl->crl->revoked, X509_REVOKED_free);
+ crl->crl->revoked = NULL;
+ for (i=0; i<RARRAY(ary)->len; i++) {
+ rev = DupX509RevokedPtr(RARRAY(ary)->ptr[i]);
+ if (!X509_CRL_add0_revoked(crl, rev)) { /* NO DUP - don't free! */
+ ossl_raise(eX509CRLError, NULL);
+ }
+ }
+ X509_CRL_sort(crl);
+
+ return ary;
+}
+
+static VALUE
+ossl_x509crl_add_revoked(VALUE self, VALUE revoked)
+{
+ X509_CRL *crl;
+ X509_REVOKED *rev;
+
+ GetX509CRL(self, crl);
+ rev = DupX509RevokedPtr(revoked);
+ if (!X509_CRL_add0_revoked(crl, rev)) { /* NO DUP - don't free! */
+ ossl_raise(eX509CRLError, NULL);
+ }
+ X509_CRL_sort(crl);
+
+ return revoked;
+}
+
+static VALUE
+ossl_x509crl_sign(VALUE self, VALUE key, VALUE digest)
+{
+ X509_CRL *crl;
+ EVP_PKEY *pkey;
+ const EVP_MD *md;
+
+ GetX509CRL(self, crl);
+ pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */
+ md = GetDigestPtr(digest);
+ if (!X509_CRL_sign(crl, pkey, md)) {
+ ossl_raise(eX509CRLError, NULL);
+ }
+
+ return self;
+}
+
+static VALUE
+ossl_x509crl_verify(VALUE self, VALUE key)
+{
+ X509_CRL *crl;
+ int ret;
+
+ GetX509CRL(self, crl);
+ if ((ret = X509_CRL_verify(crl, GetPKeyPtr(key))) < 0) {
+ ossl_raise(eX509CRLError, NULL);
+ }
+ if (ret == 1) {
+ return Qtrue;
+ }
+
+ return Qfalse;
+}
+
+static VALUE
+ossl_x509crl_to_der(VALUE self)
+{
+ X509_CRL *crl;
+ BIO *out;
+ BUF_MEM *buf;
+ VALUE str;
+
+ GetX509CRL(self, crl);
+ if (!(out = BIO_new(BIO_s_mem()))) {
+ ossl_raise(eX509CRLError, NULL);
+ }
+ if (!i2d_X509_CRL_bio(out, crl)) {
+ BIO_free(out);
+ ossl_raise(eX509CRLError, NULL);
+ }
+ BIO_get_mem_ptr(out, &buf);
+ str = rb_str_new(buf->data, buf->length);
+ BIO_free(out);
+
+ return str;
+}
+
+static VALUE
+ossl_x509crl_to_pem(VALUE self)
+{
+ X509_CRL *crl;
+ BIO *out;
+ BUF_MEM *buf;
+ VALUE str;
+
+ GetX509CRL(self, crl);
+ if (!(out = BIO_new(BIO_s_mem()))) {
+ ossl_raise(eX509CRLError, NULL);
+ }
+ if (!PEM_write_bio_X509_CRL(out, crl)) {
+ BIO_free(out);
+ ossl_raise(eX509CRLError, NULL);
+ }
+ BIO_get_mem_ptr(out, &buf);
+ str = rb_str_new(buf->data, buf->length);
+ BIO_free(out);
+
+ return str;
+}
+
+static VALUE
+ossl_x509crl_to_text(VALUE self)
+{
+ X509_CRL *crl;
+ BIO *out;
+ BUF_MEM *buf;
+ VALUE str;
+
+ GetX509CRL(self, crl);
+ if (!(out = BIO_new(BIO_s_mem()))) {
+ ossl_raise(eX509CRLError, NULL);
+ }
+ if (!X509_CRL_print(out, crl)) {
+ BIO_free(out);
+ ossl_raise(eX509CRLError, NULL);
+ }
+ BIO_get_mem_ptr(out, &buf);
+ str = rb_str_new(buf->data, buf->length);
+ BIO_free(out);
+
+ return str;
+}
+
+/*
+ * Gets X509v3 extensions as array of X509Ext objects
+ */
+static VALUE
+ossl_x509crl_get_extensions(VALUE self)
+{
+ X509_CRL *crl;
+ int count, i;
+ X509_EXTENSION *ext;
+ VALUE ary;
+
+ GetX509CRL(self, crl);
+ count = X509_CRL_get_ext_count(crl);
+ if (count < 0) {
+ OSSL_Debug("count < 0???");
+ return rb_ary_new();
+ }
+ ary = rb_ary_new2(count);
+ for (i=0; i<count; i++) {
+ ext = X509_CRL_get_ext(crl, i); /* NO DUP - don't free! */
+ rb_ary_push(ary, ossl_x509ext_new(ext));
+ }
+
+ return ary;
+}
+
+/*
+ * Sets X509_EXTENSIONs
+ */
+static VALUE
+ossl_x509crl_set_extensions(VALUE self, VALUE ary)
+{
+ X509_CRL *crl;
+ X509_EXTENSION *ext;
+ int i;
+
+ Check_Type(ary, T_ARRAY);
+ /* All ary members should be X509 Extensions */
+ for (i=0; i<RARRAY(ary)->len; i++) {
+ OSSL_Check_Kind(RARRAY(ary)->ptr[i], cX509Ext);
+ }
+ GetX509CRL(self, crl);
+ sk_X509_EXTENSION_pop_free(crl->crl->extensions, X509_EXTENSION_free);
+ crl->crl->extensions = NULL;
+ for (i=0; i<RARRAY(ary)->len; i++) {
+ ext = DupX509ExtPtr(RARRAY(ary)->ptr[i]);
+ if(!X509_CRL_add_ext(crl, ext, -1)) { /* DUPs ext - FREE it */
+ X509_EXTENSION_free(ext);
+ ossl_raise(eX509CRLError, NULL);
+ }
+ X509_EXTENSION_free(ext);
+ }
+
+ return ary;
+}
+
+static VALUE
+ossl_x509crl_add_extension(VALUE self, VALUE extension)
+{
+ X509_CRL *crl;
+ X509_EXTENSION *ext;
+
+ GetX509CRL(self, crl);
+ ext = DupX509ExtPtr(extension);
+ if (!X509_CRL_add_ext(crl, ext, -1)) { /* DUPs ext - FREE it */
+ X509_EXTENSION_free(ext);
+ ossl_raise(eX509CRLError, NULL);
+ }
+ X509_EXTENSION_free(ext);
+
+ return extension;
+}
+
+/*
+ * INIT
+ */
+void
+Init_ossl_x509crl()
+{
+ eX509CRLError = rb_define_class_under(mX509, "CRLError", eOSSLError);
+
+ cX509CRL = rb_define_class_under(mX509, "CRL", rb_cObject);
+
+ rb_define_alloc_func(cX509CRL, ossl_x509crl_alloc);
+ rb_define_method(cX509CRL, "initialize", ossl_x509crl_initialize, -1);
+ rb_define_copy_func(cX509CRL, ossl_x509crl_copy);
+
+ rb_define_method(cX509CRL, "version", ossl_x509crl_get_version, 0);
+ rb_define_method(cX509CRL, "version=", ossl_x509crl_set_version, 1);
+ rb_define_method(cX509CRL, "signature_algorithm", ossl_x509crl_get_signature_algorithm, 0);
+ rb_define_method(cX509CRL, "issuer", ossl_x509crl_get_issuer, 0);
+ rb_define_method(cX509CRL, "issuer=", ossl_x509crl_set_issuer, 1);
+ rb_define_method(cX509CRL, "last_update", ossl_x509crl_get_last_update, 0);
+ rb_define_method(cX509CRL, "last_update=", ossl_x509crl_set_last_update, 1);
+ rb_define_method(cX509CRL, "next_update", ossl_x509crl_get_next_update, 0);
+ rb_define_method(cX509CRL, "next_update=", ossl_x509crl_set_next_update, 1);
+ rb_define_method(cX509CRL, "revoked", ossl_x509crl_get_revoked, 0);
+ rb_define_method(cX509CRL, "revoked=", ossl_x509crl_set_revoked, 1);
+ rb_define_method(cX509CRL, "add_revoked", ossl_x509crl_add_revoked, 1);
+ rb_define_method(cX509CRL, "sign", ossl_x509crl_sign, 2);
+ rb_define_method(cX509CRL, "verify", ossl_x509crl_verify, 1);
+ rb_define_method(cX509CRL, "to_der", ossl_x509crl_to_der, 0);
+ rb_define_method(cX509CRL, "to_pem", ossl_x509crl_to_pem, 0);
+ rb_define_alias(cX509CRL, "to_s", "to_pem");
+ rb_define_method(cX509CRL, "to_text", ossl_x509crl_to_text, 0);
+ rb_define_method(cX509CRL, "extensions", ossl_x509crl_get_extensions, 0);
+ rb_define_method(cX509CRL, "extensions=", ossl_x509crl_set_extensions, 1);
+ rb_define_method(cX509CRL, "add_extension", ossl_x509crl_add_extension, 1);
+}
+
diff --git a/ruby_1_8_5/ext/openssl/ossl_x509ext.c b/ruby_1_8_5/ext/openssl/ossl_x509ext.c
new file mode 100644
index 0000000000..219f30d7e3
--- /dev/null
+++ b/ruby_1_8_5/ext/openssl/ossl_x509ext.c
@@ -0,0 +1,456 @@
+/*
+ * $Id: ossl_x509ext.c,v 1.8.2.3 2005/11/22 22:28:51 gotoyuzo Exp $
+ * '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'.)
+ */
+#include "ossl.h"
+
+#define WrapX509Ext(klass, obj, ext) do { \
+ if (!ext) { \
+ ossl_raise(rb_eRuntimeError, "EXT wasn't initialized!"); \
+ } \
+ obj = Data_Wrap_Struct(klass, 0, X509_EXTENSION_free, ext); \
+} while (0)
+#define GetX509Ext(obj, ext) do { \
+ Data_Get_Struct(obj, X509_EXTENSION, ext); \
+ if (!ext) { \
+ ossl_raise(rb_eRuntimeError, "EXT wasn't initialized!"); \
+ } \
+} while (0)
+#define SafeGetX509Ext(obj, ext) do { \
+ OSSL_Check_Kind(obj, cX509Ext); \
+ GetX509Ext(obj, ext); \
+} while (0)
+#define MakeX509ExtFactory(klass, obj, ctx) do { \
+ if (!(ctx = OPENSSL_malloc(sizeof(X509V3_CTX)))) \
+ ossl_raise(rb_eRuntimeError, "CTX wasn't allocated!"); \
+ X509V3_set_ctx(ctx, NULL, NULL, NULL, NULL, 0); \
+ obj = Data_Wrap_Struct(klass, 0, ossl_x509extfactory_free, ctx); \
+} while (0)
+#define GetX509ExtFactory(obj, ctx) do { \
+ Data_Get_Struct(obj, X509V3_CTX, ctx); \
+ if (!ctx) { \
+ ossl_raise(rb_eRuntimeError, "CTX wasn't initialized!"); \
+ } \
+} while (0)
+
+/*
+ * Classes
+ */
+VALUE cX509Ext;
+VALUE cX509ExtFactory;
+VALUE eX509ExtError;
+
+/*
+ * Public
+ */
+VALUE
+ossl_x509ext_new(X509_EXTENSION *ext)
+{
+ X509_EXTENSION *new;
+ VALUE obj;
+
+ if (!ext) {
+ new = X509_EXTENSION_new();
+ } else {
+ new = X509_EXTENSION_dup(ext);
+ }
+ if (!new) {
+ ossl_raise(eX509ExtError, NULL);
+ }
+ WrapX509Ext(cX509Ext, obj, new);
+
+ return obj;
+}
+
+X509_EXTENSION *
+GetX509ExtPtr(VALUE obj)
+{
+ X509_EXTENSION *ext;
+
+ SafeGetX509Ext(obj, ext);
+
+ return ext;
+}
+
+X509_EXTENSION *
+DupX509ExtPtr(VALUE obj)
+{
+ X509_EXTENSION *ext, *new;
+
+ SafeGetX509Ext(obj, ext);
+ if (!(new = X509_EXTENSION_dup(ext))) {
+ ossl_raise(eX509ExtError, NULL);
+ }
+
+ return new;
+}
+
+/*
+ * Private
+ */
+/*
+ * Ext factory
+ */
+static void
+ossl_x509extfactory_free(X509V3_CTX *ctx)
+{
+ OPENSSL_free(ctx);
+}
+
+static VALUE
+ossl_x509extfactory_alloc(VALUE klass)
+{
+ X509V3_CTX *ctx;
+ VALUE obj;
+
+ MakeX509ExtFactory(klass, obj, ctx);
+
+ return obj;
+}
+
+static VALUE
+ossl_x509extfactory_set_issuer_cert(VALUE self, VALUE cert)
+{
+ X509V3_CTX *ctx;
+
+ GetX509ExtFactory(self, ctx);
+ rb_iv_set(self, "@issuer_certificate", cert);
+ ctx->issuer_cert = GetX509CertPtr(cert); /* NO DUP NEEDED */
+
+ return cert;
+}
+
+static VALUE
+ossl_x509extfactory_set_subject_cert(VALUE self, VALUE cert)
+{
+ X509V3_CTX *ctx;
+
+ GetX509ExtFactory(self, ctx);
+ rb_iv_set(self, "@subject_certificate", cert);
+ ctx->subject_cert = GetX509CertPtr(cert); /* NO DUP NEEDED */
+
+ return cert;
+}
+
+static VALUE
+ossl_x509extfactory_set_subject_req(VALUE self, VALUE req)
+{
+ X509V3_CTX *ctx;
+
+ GetX509ExtFactory(self, ctx);
+ rb_iv_set(self, "@subject_request", req);
+ ctx->subject_req = GetX509ReqPtr(req); /* NO DUP NEEDED */
+
+ return req;
+}
+
+static VALUE
+ossl_x509extfactory_set_crl(VALUE self, VALUE crl)
+{
+ X509V3_CTX *ctx;
+
+ GetX509ExtFactory(self, ctx);
+ rb_iv_set(self, "@crl", crl);
+ ctx->crl = GetX509CRLPtr(crl); /* NO DUP NEEDED */
+
+ return crl;
+}
+
+static VALUE
+ossl_x509extfactory_set_config(VALUE self, VALUE config)
+{
+#ifdef HAVE_X509V3_SET_NCONF
+ X509V3_CTX *ctx;
+ CONF *conf;
+
+ GetX509ExtFactory(self, ctx);
+ rb_iv_set(self, "@config", config);
+ conf = GetConfigPtr(config); /* NO DUP NEEDED */
+ X509V3_set_nconf(ctx, conf);
+
+ return config;
+#else
+ rb_notimplement();
+#endif
+}
+
+static VALUE
+ossl_x509extfactory_initialize(int argc, VALUE *argv, VALUE self)
+{
+ /*X509V3_CTX *ctx;*/
+ VALUE issuer_cert, subject_cert, subject_req, crl;
+
+ /*GetX509ExtFactory(self, ctx);*/
+
+ 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))
+ ossl_x509extfactory_set_subject_cert(self, subject_cert);
+ if (!NIL_P(subject_req))
+ ossl_x509extfactory_set_subject_req(self, subject_req);
+ if (!NIL_P(crl))
+ ossl_x509extfactory_set_crl(self, crl);
+
+ return self;
+}
+
+/*
+ * Array to X509_EXTENSION
+ * Structure:
+ * ["ln", "value", bool_critical] or
+ * ["sn", "value", bool_critical] or
+ * ["ln", "critical,value"] or the same for sn
+ * ["ln", "value"] => not critical
+ */
+static VALUE
+ossl_x509extfactory_create_ext(int argc, VALUE *argv, VALUE self)
+{
+ X509V3_CTX *ctx;
+ X509_EXTENSION *ext;
+ VALUE oid, value, critical, valstr, obj;
+ int nid;
+#ifdef HAVE_X509V3_EXT_NCONF_NID
+ VALUE rconf;
+ CONF *conf;
+#else
+ static LHASH *empty_lhash;
+#endif
+
+ 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, "unknown OID `%s'", RSTRING(oid)->ptr);
+ valstr = rb_str_new2(RTEST(critical) ? "critical," : "");
+ rb_str_append(valstr, value);
+ GetX509ExtFactory(self, ctx);
+#ifdef HAVE_X509V3_EXT_NCONF_NID
+ rconf = rb_iv_get(self, "@config");
+ conf = NIL_P(rconf) ? NULL : GetConfigPtr(rconf);
+ ext = X509V3_EXT_nconf_nid(conf, ctx, nid, RSTRING(valstr)->ptr);
+#else
+ if (!empty_lhash) empty_lhash = lh_new(NULL, NULL);
+ ext = X509V3_EXT_conf_nid(empty_lhash, ctx, nid, RSTRING(valstr)->ptr);
+#endif
+ if (!ext){
+ ossl_raise(eX509ExtError, "%s = %s",
+ RSTRING(oid)->ptr, RSTRING(value)->ptr);
+ }
+ WrapX509Ext(cX509Ext, obj, ext);
+
+ return obj;
+}
+
+/*
+ * Ext
+ */
+static VALUE
+ossl_x509ext_alloc(VALUE klass)
+{
+ X509_EXTENSION *ext;
+ VALUE obj;
+
+ if(!(ext = X509_EXTENSION_new())){
+ ossl_raise(eX509ExtError, NULL);
+ }
+ WrapX509Ext(klass, obj, ext);
+
+ return obj;
+}
+
+static VALUE
+ossl_x509ext_initialize(int argc, VALUE *argv, VALUE self)
+{
+ VALUE oid, value, critical;
+ unsigned char *p;
+ X509_EXTENSION *ext;
+
+ GetX509Ext(self, ext);
+ if(rb_scan_args(argc, argv, "12", &oid, &value, &critical) == 1){
+ oid = ossl_to_der_if_possible(oid);
+ StringValue(oid);
+ p = RSTRING(oid)->ptr;
+ if(!d2i_X509_EXTENSION((X509_EXTENSION**)&DATA_PTR(self),
+ &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);
+
+ return self;
+}
+
+static VALUE
+ossl_x509ext_set_oid(VALUE self, VALUE oid)
+{
+ X509_EXTENSION *ext;
+ ASN1_OBJECT *obj;
+ char *s;
+
+ s = StringValuePtr(oid);
+ obj = OBJ_txt2obj(s, 0);
+ if(!obj) obj = OBJ_txt2obj(s, 1);
+ if(!obj) ossl_raise(eX509ExtError, NULL);
+ GetX509Ext(self, ext);
+ X509_EXTENSION_set_object(ext, obj);
+
+ return oid;
+}
+
+static VALUE
+ossl_x509ext_set_value(VALUE self, VALUE data)
+{
+ X509_EXTENSION *ext;
+ ASN1_OCTET_STRING *asn1s;
+ char *s;
+
+ data = ossl_to_der_if_possible(data);
+ StringValue(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);
+ ossl_raise(eX509ExtError, NULL);
+ }
+ if(!M_ASN1_OCTET_STRING_set(asn1s, s, RSTRING(data)->len)){
+ free(s);
+ ASN1_OCTET_STRING_free(asn1s);
+ ossl_raise(eX509ExtError, NULL);
+ }
+ GetX509Ext(self, ext);
+ X509_EXTENSION_set_data(ext, asn1s);
+
+ return data;
+}
+
+static VALUE
+ossl_x509ext_set_critical(VALUE self, VALUE flag)
+{
+ X509_EXTENSION *ext;
+
+ GetX509Ext(self, ext);
+ X509_EXTENSION_set_critical(ext, RTEST(flag) ? 1 : 0);
+
+ return flag;
+}
+
+static VALUE
+ossl_x509ext_get_oid(VALUE obj)
+{
+ X509_EXTENSION *ext;
+ ASN1_OBJECT *extobj;
+ BIO *out;
+ VALUE ret;
+ int nid;
+
+ GetX509Ext(obj, ext);
+ extobj = X509_EXTENSION_get_object(ext);
+ if ((nid = OBJ_obj2nid(extobj)) != NID_undef)
+ ret = rb_str_new2(OBJ_nid2sn(nid));
+ else{
+ if (!(out = BIO_new(BIO_s_mem())))
+ ossl_raise(eX509ExtError, NULL);
+ i2a_ASN1_OBJECT(out, extobj);
+ ret = ossl_membio2str(out);
+ }
+
+ return ret;
+}
+
+static VALUE
+ossl_x509ext_get_value(VALUE obj)
+{
+ X509_EXTENSION *ext;
+ BIO *out;
+ VALUE ret;
+
+ 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_membio2str(out);
+
+ return ret;
+}
+
+static VALUE
+ossl_x509ext_get_critical(VALUE obj)
+{
+ X509_EXTENSION *ext;
+
+ GetX509Ext(obj, ext);
+ return X509_EXTENSION_get_critical(ext) ? Qtrue : Qfalse;
+}
+
+static VALUE
+ossl_x509ext_to_der(VALUE obj)
+{
+ X509_EXTENSION *ext;
+ unsigned char *p;
+ long len;
+ VALUE str;
+
+ GetX509Ext(obj, ext);
+ 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;
+}
+
+/*
+ * INIT
+ */
+void
+Init_ossl_x509ext()
+{
+ eX509ExtError = rb_define_class_under(mX509, "ExtensionError", eOSSLError);
+
+ cX509ExtFactory = rb_define_class_under(mX509, "ExtensionFactory", rb_cObject);
+
+ rb_define_alloc_func(cX509ExtFactory, ossl_x509extfactory_alloc);
+ rb_define_method(cX509ExtFactory, "initialize", ossl_x509extfactory_initialize, -1);
+
+ rb_attr(cX509ExtFactory, rb_intern("issuer_certificate"), 1, 0, Qfalse);
+ rb_attr(cX509ExtFactory, rb_intern("subject_certificate"), 1, 0, Qfalse);
+ rb_attr(cX509ExtFactory, rb_intern("subject_request"), 1, 0, Qfalse);
+ rb_attr(cX509ExtFactory, rb_intern("crl"), 1, 0, Qfalse);
+ rb_attr(cX509ExtFactory, rb_intern("config"), 1, 0, Qfalse);
+
+ rb_define_method(cX509ExtFactory, "issuer_certificate=", ossl_x509extfactory_set_issuer_cert, 1);
+ rb_define_method(cX509ExtFactory, "subject_certificate=", ossl_x509extfactory_set_subject_cert, 1);
+ 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", ossl_x509extfactory_create_ext, -1);
+
+ cX509Ext = rb_define_class_under(mX509, "Extension", rb_cObject);
+ rb_define_alloc_func(cX509Ext, ossl_x509ext_alloc);
+ rb_define_method(cX509Ext, "initialize", ossl_x509ext_initialize, -1);
+ rb_define_method(cX509Ext, "oid=", ossl_x509ext_set_oid, 1);
+ rb_define_method(cX509Ext, "value=", ossl_x509ext_set_value, 1);
+ rb_define_method(cX509Ext, "critical=", ossl_x509ext_set_critical, 1);
+ rb_define_method(cX509Ext, "oid", ossl_x509ext_get_oid, 0);
+ rb_define_method(cX509Ext, "value", ossl_x509ext_get_value, 0);
+ rb_define_method(cX509Ext, "critical?", ossl_x509ext_get_critical, 0);
+ rb_define_method(cX509Ext, "to_der", ossl_x509ext_to_der, 0);
+}
diff --git a/ruby_1_8_5/ext/openssl/ossl_x509name.c b/ruby_1_8_5/ext/openssl/ossl_x509name.c
new file mode 100644
index 0000000000..1a456f2c48
--- /dev/null
+++ b/ruby_1_8_5/ext/openssl/ossl_x509name.c
@@ -0,0 +1,344 @@
+/*
+ * $Id: ossl_x509name.c,v 1.4.2.8 2004/12/27 07:55:56 gotoyuzo Exp $
+ * 'OpenSSL for Ruby' project
+ * Copyright (C) 2001 Michal Rokos <m.rokos@sh.cvut.cz>
+ * All rights reserved.
+ */
+/*
+ * This program is licenced under the same licence as Ruby.
+ * (See the file 'LICENCE'.)
+ */
+#include "ossl.h"
+
+#define WrapX509Name(klass, obj, name) do { \
+ if (!name) { \
+ ossl_raise(rb_eRuntimeError, "Name wasn't initialized."); \
+ } \
+ obj = Data_Wrap_Struct(klass, 0, X509_NAME_free, name); \
+} while (0)
+#define GetX509Name(obj, name) do { \
+ Data_Get_Struct(obj, X509_NAME, name); \
+ if (!name) { \
+ ossl_raise(rb_eRuntimeError, "Name wasn't initialized."); \
+ } \
+} while (0)
+#define SafeGetX509Name(obj, name) do { \
+ OSSL_Check_Kind(obj, cX509Name); \
+ GetX509Name(obj, name); \
+} while (0)
+
+#define OBJECT_TYPE_TEMPLATE \
+ rb_const_get(cX509Name, rb_intern("OBJECT_TYPE_TEMPLATE"))
+#define DEFAULT_OBJECT_TYPE \
+ rb_const_get(cX509Name, rb_intern("DEFAULT_OBJECT_TYPE"))
+
+/*
+ * Classes
+ */
+VALUE cX509Name;
+VALUE eX509NameError;
+
+/*
+ * Public
+ */
+VALUE
+ossl_x509name_new(X509_NAME *name)
+{
+ X509_NAME *new;
+ VALUE obj;
+
+ if (!name) {
+ new = X509_NAME_new();
+ } else {
+ new = X509_NAME_dup(name);
+ }
+ if (!new) {
+ ossl_raise(eX509NameError, NULL);
+ }
+ WrapX509Name(cX509Name, obj, new);
+
+ return obj;
+}
+
+X509_NAME *
+GetX509NamePtr(VALUE obj)
+{
+ X509_NAME *name;
+
+ SafeGetX509Name(obj, name);
+
+ return name;
+}
+
+/*
+ * Private
+ */
+static VALUE
+ossl_x509name_alloc(VALUE klass)
+{
+ X509_NAME *name;
+ VALUE obj;
+
+ if (!(name = X509_NAME_new())) {
+ ossl_raise(eX509NameError, NULL);
+ }
+ WrapX509Name(klass, obj, name);
+
+ return obj;
+}
+
+static int id_aref;
+static VALUE ossl_x509name_add_entry(int, VALUE*, VALUE);
+#define rb_aref(obj, key) rb_funcall(obj, id_aref, 1, key)
+
+static VALUE
+ossl_x509name_init_i(VALUE i, VALUE args)
+{
+ VALUE self = rb_ary_entry(args, 0);
+ VALUE template = rb_ary_entry(args, 1);
+ VALUE entry[3];
+
+ Check_Type(i, T_ARRAY);
+ entry[0] = rb_ary_entry(i, 0);
+ entry[1] = rb_ary_entry(i, 1);
+ entry[2] = rb_ary_entry(i, 2);
+ if(NIL_P(entry[2])) entry[2] = rb_aref(template, entry[0]);
+ if(NIL_P(entry[2])) entry[2] = DEFAULT_OBJECT_TYPE;
+ ossl_x509name_add_entry(3, entry, self);
+
+ return Qnil;
+}
+
+static VALUE
+ossl_x509name_initialize(int argc, VALUE *argv, VALUE self)
+{
+ X509_NAME *name;
+ VALUE arg, template;
+
+ GetX509Name(self, name);
+ if (rb_scan_args(argc, argv, "02", &arg, &template) == 0) {
+ return self;
+ }
+ else {
+ VALUE tmp = rb_check_array_type(arg);
+ if (!NIL_P(tmp)) {
+ VALUE args;
+ if(NIL_P(template)) template = OBJECT_TYPE_TEMPLATE;
+ args = rb_ary_new3(2, self, template);
+ rb_iterate(rb_each, tmp, ossl_x509name_init_i, args);
+ }
+ else{
+ unsigned char *p;
+ VALUE str = ossl_to_der_if_possible(arg);
+ StringValue(str);
+ p = RSTRING(str)->ptr;
+ if(!d2i_X509_NAME((X509_NAME**)&DATA_PTR(self), &p, RSTRING(str)->len)){
+ ossl_raise(eX509NameError, NULL);
+ }
+ }
+ }
+
+ return self;
+}
+
+static
+VALUE ossl_x509name_add_entry(int argc, VALUE *argv, VALUE self)
+{
+ X509_NAME *name;
+ VALUE oid, value, type;
+
+ rb_scan_args(argc, argv, "21", &oid, &value, &type);
+ StringValue(oid);
+ StringValue(value);
+ if(NIL_P(type)) type = rb_aref(OBJECT_TYPE_TEMPLATE, oid);
+ GetX509Name(self, name);
+ if (!X509_NAME_add_entry_by_txt(name, RSTRING(oid)->ptr, NUM2INT(type),
+ RSTRING(value)->ptr, RSTRING(value)->len, -1, 0)) {
+ ossl_raise(eX509NameError, NULL);
+ }
+
+ return self;
+}
+
+static VALUE
+ossl_x509name_to_s_old(VALUE self)
+{
+ X509_NAME *name;
+ char *buf;
+ VALUE str;
+
+ GetX509Name(self, name);
+ buf = X509_NAME_oneline(name, NULL, 0);
+ str = rb_str_new2(buf);
+ OPENSSL_free(buf);
+
+ return str;
+}
+
+static VALUE
+ossl_x509name_to_s(int argc, VALUE *argv, VALUE self)
+{
+ X509_NAME *name;
+ VALUE flag, str;
+ BIO *out;
+ unsigned long iflag;
+
+ rb_scan_args(argc, argv, "01", &flag);
+ if (NIL_P(flag))
+ return ossl_x509name_to_s_old(self);
+ else iflag = NUM2ULONG(flag);
+ if (!(out = BIO_new(BIO_s_mem())))
+ ossl_raise(eX509NameError, NULL);
+ GetX509Name(self, name);
+ if (!X509_NAME_print_ex(out, name, 0, iflag)){
+ BIO_free(out);
+ ossl_raise(eX509NameError, NULL);
+ }
+ str = ossl_membio2str(out);
+
+ return str;
+}
+
+static VALUE
+ossl_x509name_to_a(VALUE self)
+{
+ X509_NAME *name;
+ X509_NAME_ENTRY *entry;
+ int i,entries;
+ char long_name[512];
+ const char *short_name;
+ VALUE ary, ret;
+
+ GetX509Name(self, name);
+ entries = X509_NAME_entry_count(name);
+ if (entries < 0) {
+ OSSL_Debug("name entries < 0!");
+ return rb_ary_new();
+ }
+ ret = rb_ary_new2(entries);
+ for (i=0; i<entries; i++) {
+ if (!(entry = X509_NAME_get_entry(name, i))) {
+ ossl_raise(eX509NameError, NULL);
+ }
+ if (!i2t_ASN1_OBJECT(long_name, sizeof(long_name), entry->object)) {
+ ossl_raise(eX509NameError, NULL);
+ }
+ short_name = OBJ_nid2sn(OBJ_ln2nid(long_name));
+ ary = rb_ary_new3(3, rb_str_new2(short_name),
+ rb_str_new(entry->value->data, entry->value->length),
+ INT2FIX(entry->value->type));
+ rb_ary_push(ret, ary);
+ }
+ return ret;
+}
+
+static int
+ossl_x509name_cmp0(VALUE self, VALUE other)
+{
+ X509_NAME *name1, *name2;
+
+ GetX509Name(self, name1);
+ SafeGetX509Name(other, name2);
+
+ return X509_NAME_cmp(name1, name2);
+}
+
+static VALUE
+ossl_x509name_cmp(VALUE self, VALUE other)
+{
+ int result;
+
+ result = ossl_x509name_cmp0(self, other);
+ if (result < 0) return INT2FIX(-1);
+ if (result > 1) return INT2FIX(1);
+
+ return INT2FIX(0);
+}
+
+static VALUE
+ossl_x509name_eql(VALUE self, VALUE other)
+{
+ int result;
+
+ if(CLASS_OF(other) != cX509Name) return Qfalse;
+ result = ossl_x509name_cmp0(self, other);
+
+ return (result == 0) ? Qtrue : Qfalse;
+}
+
+static VALUE
+ossl_x509name_hash(VALUE self)
+{
+ X509_NAME *name;
+ unsigned long hash;
+
+ GetX509Name(self, name);
+
+ hash = X509_NAME_hash(name);
+
+ 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
+ */
+void
+Init_ossl_x509name()
+{
+ VALUE utf8str, ptrstr, ia5str, hash;
+
+ id_aref = rb_intern("[]");
+ eX509NameError = rb_define_class_under(mX509, "NameError", eOSSLError);
+ cX509Name = rb_define_class_under(mX509, "Name", rb_cObject);
+
+ rb_define_alloc_func(cX509Name, ossl_x509name_alloc);
+ rb_define_method(cX509Name, "initialize", ossl_x509name_initialize, -1);
+ rb_define_method(cX509Name, "add_entry", ossl_x509name_add_entry, -1);
+ rb_define_method(cX509Name, "to_s", ossl_x509name_to_s, -1);
+ 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);
+
+ utf8str = INT2NUM(V_ASN1_UTF8STRING);
+ ptrstr = INT2NUM(V_ASN1_PRINTABLESTRING);
+ ia5str = INT2NUM(V_ASN1_IA5STRING);
+ rb_define_const(cX509Name, "DEFAULT_OBJECT_TYPE", utf8str);
+ hash = rb_hash_new();
+ RHASH(hash)->ifnone = utf8str;
+ rb_hash_aset(hash, rb_str_new2("C"), ptrstr);
+ rb_hash_aset(hash, rb_str_new2("countryName"), ptrstr);
+ rb_hash_aset(hash, rb_str_new2("serialNumber"), ptrstr);
+ rb_hash_aset(hash, rb_str_new2("dnQualifier"), ptrstr);
+ rb_hash_aset(hash, rb_str_new2("DC"), ia5str);
+ rb_hash_aset(hash, rb_str_new2("domainComponent"), ia5str);
+ rb_hash_aset(hash, rb_str_new2("emailAddress"), ia5str);
+ rb_define_const(cX509Name, "OBJECT_TYPE_TEMPLATE", hash);
+
+ rb_define_const(cX509Name, "COMPAT", ULONG2NUM(XN_FLAG_COMPAT));
+ rb_define_const(cX509Name, "RFC2253", ULONG2NUM(XN_FLAG_RFC2253));
+ rb_define_const(cX509Name, "ONELINE", ULONG2NUM(XN_FLAG_ONELINE));
+ rb_define_const(cX509Name, "MULTILINE", ULONG2NUM(XN_FLAG_MULTILINE));
+}
diff --git a/ruby_1_8_5/ext/openssl/ossl_x509req.c b/ruby_1_8_5/ext/openssl/ossl_x509req.c
new file mode 100644
index 0000000000..c1b1a3e619
--- /dev/null
+++ b/ruby_1_8_5/ext/openssl/ossl_x509req.c
@@ -0,0 +1,466 @@
+/*
+ * $Id: ossl_x509req.c,v 1.5.2.2 2005/09/10 00:54:29 gotoyuzo Exp $
+ * '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'.)
+ */
+#include "ossl.h"
+
+#define WrapX509Req(klass, obj, req) do { \
+ if (!req) { \
+ ossl_raise(rb_eRuntimeError, "Req wasn't initialized!"); \
+ } \
+ obj = Data_Wrap_Struct(klass, 0, X509_REQ_free, req); \
+} while (0)
+#define GetX509Req(obj, req) do { \
+ Data_Get_Struct(obj, X509_REQ, req); \
+ if (!req) { \
+ ossl_raise(rb_eRuntimeError, "Req wasn't initialized!"); \
+ } \
+} while (0)
+#define SafeGetX509Req(obj, req) do { \
+ OSSL_Check_Kind(obj, cX509Req); \
+ GetX509Req(obj, req); \
+} while (0)
+
+/*
+ * Classes
+ */
+VALUE cX509Req;
+VALUE eX509ReqError;
+
+/*
+ * Public functions
+ */
+VALUE
+ossl_x509req_new(X509_REQ *req)
+{
+ X509_REQ *new;
+ VALUE obj;
+
+ if (!req) {
+ new = X509_REQ_new();
+ } else {
+ new = X509_REQ_dup(req);
+ }
+ if (!new) {
+ ossl_raise(eX509ReqError, NULL);
+ }
+ WrapX509Req(cX509Req, obj, new);
+
+ return obj;
+}
+
+X509_REQ *
+GetX509ReqPtr(VALUE obj)
+{
+ X509_REQ *req;
+
+ SafeGetX509Req(obj, req);
+
+ return req;
+}
+
+X509_REQ *
+DupX509ReqPtr(VALUE obj)
+{
+ X509_REQ *req, *new;
+
+ SafeGetX509Req(obj, req);
+ if (!(new = X509_REQ_dup(req))) {
+ ossl_raise(eX509ReqError, NULL);
+ }
+
+ return new;
+}
+
+/*
+ * Private functions
+ */
+static VALUE
+ossl_x509req_alloc(VALUE klass)
+{
+ X509_REQ *req;
+ VALUE obj;
+
+ if (!(req = X509_REQ_new())) {
+ ossl_raise(eX509ReqError, NULL);
+ }
+ WrapX509Req(klass, obj, req);
+
+ return obj;
+}
+
+static VALUE
+ossl_x509req_initialize(int argc, VALUE *argv, VALUE self)
+{
+ BIO *in;
+ X509_REQ *req;
+ VALUE arg;
+
+ if (rb_scan_args(argc, argv, "01", &arg) == 0) {
+ return 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));
+ }
+ BIO_free(in);
+ if (!req) ossl_raise(eX509ReqError, NULL);
+
+ return self;
+}
+
+static VALUE
+ossl_x509req_copy(VALUE self, VALUE other)
+{
+ X509_REQ *a, *b, *req;
+
+ rb_check_frozen(self);
+ if (self == other) return self;
+ GetX509Req(self, a);
+ SafeGetX509Req(other, b);
+ if (!(req = X509_REQ_dup(b))) {
+ ossl_raise(eX509ReqError, NULL);
+ }
+ X509_REQ_free(a);
+ DATA_PTR(self) = req;
+
+ return self;
+}
+
+static VALUE
+ossl_x509req_to_pem(VALUE self)
+{
+ X509_REQ *req;
+ BIO *out;
+ BUF_MEM *buf;
+ VALUE str;
+
+ GetX509Req(self, req);
+ if (!(out = BIO_new(BIO_s_mem()))) {
+ ossl_raise(eX509ReqError, NULL);
+ }
+ if (!PEM_write_bio_X509_REQ(out, req)) {
+ BIO_free(out);
+ ossl_raise(eX509ReqError, NULL);
+ }
+ BIO_get_mem_ptr(out, &buf);
+ str = rb_str_new(buf->data, buf->length);
+ BIO_free(out);
+
+ return str;
+}
+
+static VALUE
+ossl_x509req_to_der(VALUE self)
+{
+ X509_REQ *req;
+ VALUE str;
+ long len;
+ unsigned char *p;
+
+ GetX509Req(self, req);
+ if ((len = i2d_X509_REQ(req, NULL)) <= 0)
+ ossl_raise(eX509CertError, NULL);
+ str = rb_str_new(0, len);
+ p = RSTRING(str)->ptr;
+ if (i2d_X509_REQ(req, &p) <= 0)
+ ossl_raise(eX509ReqError, NULL);
+ ossl_str_adjust(str, p);
+
+ return str;
+}
+
+static VALUE
+ossl_x509req_to_text(VALUE self)
+{
+ X509_REQ *req;
+ BIO *out;
+ BUF_MEM *buf;
+ VALUE str;
+
+ GetX509Req(self, req);
+ if (!(out = BIO_new(BIO_s_mem()))) {
+ ossl_raise(eX509ReqError, NULL);
+ }
+ if (!X509_REQ_print(out, req)) {
+ BIO_free(out);
+ ossl_raise(eX509ReqError, NULL);
+ }
+ BIO_get_mem_ptr(out, &buf);
+ str = rb_str_new(buf->data, buf->length);
+ BIO_free(out);
+
+ return str;
+}
+
+#if 0
+/*
+ * Makes X509 from X509_REQuest
+ */
+static VALUE
+ossl_x509req_to_x509(VALUE self, VALUE days, VALUE key)
+{
+ X509_REQ *req;
+ X509 *x509;
+
+ GetX509Req(self, req);
+ ...
+ if (!(x509 = X509_REQ_to_X509(req, d, pkey))) {
+ ossl_raise(eX509ReqError, NULL);
+ }
+
+ return ossl_x509_new(x509);
+}
+#endif
+
+static VALUE
+ossl_x509req_get_version(VALUE self)
+{
+ X509_REQ *req;
+ long version;
+
+ GetX509Req(self, req);
+ version = X509_REQ_get_version(req);
+
+ return LONG2FIX(version);
+}
+
+static VALUE
+ossl_x509req_set_version(VALUE self, VALUE version)
+{
+ X509_REQ *req;
+ long ver;
+
+ if ((ver = FIX2LONG(version)) < 0) {
+ ossl_raise(eX509ReqError, "version must be >= 0!");
+ }
+ GetX509Req(self, req);
+ if (!X509_REQ_set_version(req, ver)) {
+ ossl_raise(eX509ReqError, NULL);
+ }
+
+ return version;
+}
+
+static VALUE
+ossl_x509req_get_subject(VALUE self)
+{
+ X509_REQ *req;
+ X509_NAME *name;
+
+ GetX509Req(self, req);
+ if (!(name = X509_REQ_get_subject_name(req))) { /* NO DUP - don't free */
+ ossl_raise(eX509ReqError, NULL);
+ }
+
+ return ossl_x509name_new(name);
+}
+
+static VALUE
+ossl_x509req_set_subject(VALUE self, VALUE subject)
+{
+ X509_REQ *req;
+
+ GetX509Req(self, req);
+ /* DUPs name */
+ if (!X509_REQ_set_subject_name(req, GetX509NamePtr(subject))) {
+ ossl_raise(eX509ReqError, NULL);
+ }
+
+ return subject;
+}
+
+static VALUE
+ossl_x509req_get_signature_algorithm(VALUE self)
+{
+ X509_REQ *req;
+ BIO *out;
+ BUF_MEM *buf;
+ VALUE str;
+
+ GetX509Req(self, req);
+
+ if (!(out = BIO_new(BIO_s_mem()))) {
+ ossl_raise(eX509ReqError, NULL);
+ }
+ if (!i2a_ASN1_OBJECT(out, req->sig_alg->algorithm)) {
+ BIO_free(out);
+ ossl_raise(eX509ReqError, NULL);
+ }
+ BIO_get_mem_ptr(out, &buf);
+ str = rb_str_new(buf->data, buf->length);
+ BIO_free(out);
+ return str;
+}
+
+static VALUE
+ossl_x509req_get_public_key(VALUE self)
+{
+ X509_REQ *req;
+ EVP_PKEY *pkey;
+
+ GetX509Req(self, req);
+ if (!(pkey = X509_REQ_get_pubkey(req))) { /* adds reference */
+ ossl_raise(eX509ReqError, NULL);
+ }
+
+ return ossl_pkey_new(pkey); /* NO DUP - OK */
+}
+
+static VALUE
+ossl_x509req_set_public_key(VALUE self, VALUE key)
+{
+ X509_REQ *req;
+ EVP_PKEY *pkey;
+
+ GetX509Req(self, req);
+ pkey = GetPKeyPtr(key); /* NO NEED TO DUP */
+ if (!X509_REQ_set_pubkey(req, pkey)) {
+ ossl_raise(eX509ReqError, NULL);
+ }
+
+ return key;
+}
+
+static VALUE
+ossl_x509req_sign(VALUE self, VALUE key, VALUE digest)
+{
+ X509_REQ *req;
+ EVP_PKEY *pkey;
+ const EVP_MD *md;
+
+ GetX509Req(self, req);
+ pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */
+ md = GetDigestPtr(digest);
+ if (!X509_REQ_sign(req, pkey, md)) {
+ ossl_raise(eX509ReqError, NULL);
+ }
+
+ return self;
+}
+
+/*
+ * Checks that cert signature is made with PRIVversion of this PUBLIC 'key'
+ */
+static VALUE
+ossl_x509req_verify(VALUE self, VALUE key)
+{
+ X509_REQ *req;
+ EVP_PKEY *pkey;
+ int i;
+
+ GetX509Req(self, req);
+ pkey = GetPKeyPtr(key); /* NO NEED TO DUP */
+ if ((i = X509_REQ_verify(req, pkey)) < 0) {
+ ossl_raise(eX509ReqError, NULL);
+ }
+ if (i > 0) {
+ return Qtrue;
+ }
+
+ return Qfalse;
+}
+
+static VALUE
+ossl_x509req_get_attributes(VALUE self)
+{
+ X509_REQ *req;
+ int count, i;
+ X509_ATTRIBUTE *attr;
+ VALUE ary;
+
+ GetX509Req(self, req);
+
+ count = X509_REQ_get_attr_count(req);
+ if (count < 0) {
+ OSSL_Debug("count < 0???");
+ return rb_ary_new();
+ }
+ ary = rb_ary_new2(count);
+ for (i=0; i<count; i++) {
+ attr = X509_REQ_get_attr(req, i);
+ rb_ary_push(ary, ossl_x509attr_new(attr));
+ }
+
+ return ary;
+}
+
+static VALUE
+ossl_x509req_set_attributes(VALUE self, VALUE ary)
+{
+ X509_REQ *req;
+ X509_ATTRIBUTE *attr;
+ int i;
+ VALUE item;
+
+ Check_Type(ary, T_ARRAY);
+ for (i=0;i<RARRAY(ary)->len; i++) {
+ OSSL_Check_Kind(RARRAY(ary)->ptr[i], cX509Attr);
+ }
+ GetX509Req(self, req);
+ sk_X509_ATTRIBUTE_pop_free(req->req_info->attributes, X509_ATTRIBUTE_free);
+ req->req_info->attributes = NULL;
+ for (i=0;i<RARRAY(ary)->len; i++) {
+ item = RARRAY(ary)->ptr[i];
+ attr = DupX509AttrPtr(item);
+ if (!X509_REQ_add1_attr(req, attr)) {
+ ossl_raise(eX509ReqError, NULL);
+ }
+ }
+ return ary;
+}
+
+static VALUE
+ossl_x509req_add_attribute(VALUE self, VALUE attr)
+{
+ X509_REQ *req;
+
+ GetX509Req(self, req);
+ if (!X509_REQ_add1_attr(req, DupX509AttrPtr(attr))) {
+ ossl_raise(eX509ReqError, NULL);
+ }
+
+ return attr;
+}
+
+/*
+ * X509_REQUEST init
+ */
+void
+Init_ossl_x509req()
+{
+ eX509ReqError = rb_define_class_under(mX509, "RequestError", eOSSLError);
+
+ cX509Req = rb_define_class_under(mX509, "Request", rb_cObject);
+
+ rb_define_alloc_func(cX509Req, ossl_x509req_alloc);
+ rb_define_method(cX509Req, "initialize", ossl_x509req_initialize, -1);
+ rb_define_copy_func(cX509Req, ossl_x509req_copy);
+
+ rb_define_method(cX509Req, "to_pem", ossl_x509req_to_pem, 0);
+ rb_define_method(cX509Req, "to_der", ossl_x509req_to_der, 0);
+ rb_define_alias(cX509Req, "to_s", "to_pem");
+ rb_define_method(cX509Req, "to_text", ossl_x509req_to_text, 0);
+ rb_define_method(cX509Req, "version", ossl_x509req_get_version, 0);
+ rb_define_method(cX509Req, "version=", ossl_x509req_set_version, 1);
+ rb_define_method(cX509Req, "subject", ossl_x509req_get_subject, 0);
+ rb_define_method(cX509Req, "subject=", ossl_x509req_set_subject, 1);
+ rb_define_method(cX509Req, "signature_algorithm", ossl_x509req_get_signature_algorithm, 0);
+ rb_define_method(cX509Req, "public_key", ossl_x509req_get_public_key, 0);
+ rb_define_method(cX509Req, "public_key=", ossl_x509req_set_public_key, 1);
+ rb_define_method(cX509Req, "sign", ossl_x509req_sign, 2);
+ rb_define_method(cX509Req, "verify", ossl_x509req_verify, 1);
+ rb_define_method(cX509Req, "attributes", ossl_x509req_get_attributes, 0);
+ rb_define_method(cX509Req, "attributes=", ossl_x509req_set_attributes, 1);
+ rb_define_method(cX509Req, "add_attribute", ossl_x509req_add_attribute, 1);
+}
+
diff --git a/ruby_1_8_5/ext/openssl/ossl_x509revoked.c b/ruby_1_8_5/ext/openssl/ossl_x509revoked.c
new file mode 100644
index 0000000000..a0f2f00aa5
--- /dev/null
+++ b/ruby_1_8_5/ext/openssl/ossl_x509revoked.c
@@ -0,0 +1,229 @@
+/*
+ * $Id: ossl_x509revoked.c,v 1.2.2.1 2004/12/15 01:54:38 matz Exp $
+ * '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'.)
+ */
+#include "ossl.h"
+
+#define WrapX509Rev(klass, obj, rev) do { \
+ if (!rev) { \
+ ossl_raise(rb_eRuntimeError, "REV wasn't initialized!"); \
+ } \
+ obj = Data_Wrap_Struct(klass, 0, X509_REVOKED_free, rev); \
+} while (0)
+#define GetX509Rev(obj, rev) do { \
+ Data_Get_Struct(obj, X509_REVOKED, rev); \
+ if (!rev) { \
+ ossl_raise(rb_eRuntimeError, "REV wasn't initialized!"); \
+ } \
+} while (0)
+#define SafeGetX509Rev(obj, rev) do { \
+ OSSL_Check_Kind(obj, cX509Rev); \
+ GetX509Rev(obj, rev); \
+} while (0)
+
+/*
+ * Classes
+ */
+VALUE cX509Rev;
+VALUE eX509RevError;
+
+/*
+ * PUBLIC
+ */
+VALUE
+ossl_x509revoked_new(X509_REVOKED *rev)
+{
+ X509_REVOKED *new;
+ VALUE obj;
+
+ if (!rev) {
+ new = X509_REVOKED_new();
+ } else {
+ new = X509_REVOKED_dup(rev);
+ }
+ if (!new) {
+ ossl_raise(eX509RevError, NULL);
+ }
+ WrapX509Rev(cX509Rev, obj, new);
+
+ return obj;
+}
+
+X509_REVOKED *
+DupX509RevokedPtr(VALUE obj)
+{
+ X509_REVOKED *rev, *new;
+
+ SafeGetX509Rev(obj, rev);
+ if (!(new = X509_REVOKED_dup(rev))) {
+ ossl_raise(eX509RevError, NULL);
+ }
+
+ return new;
+}
+
+/*
+ * PRIVATE
+ */
+static VALUE
+ossl_x509revoked_alloc(VALUE klass)
+{
+ X509_REVOKED *rev;
+ VALUE obj;
+
+ if (!(rev = X509_REVOKED_new())) {
+ ossl_raise(eX509RevError, NULL);
+ }
+ WrapX509Rev(klass, obj, rev);
+
+ return obj;
+}
+
+static VALUE
+ossl_x509revoked_initialize(int argc, VALUE *argv, VALUE self)
+{
+ /* EMPTY */
+ return self;
+}
+
+static VALUE
+ossl_x509revoked_get_serial(VALUE self)
+{
+ X509_REVOKED *rev;
+
+ GetX509Rev(self, rev);
+
+ return asn1integer_to_num(rev->serialNumber);
+}
+
+static VALUE
+ossl_x509revoked_set_serial(VALUE self, VALUE num)
+{
+ X509_REVOKED *rev;
+
+ GetX509Rev(self, rev);
+ rev->serialNumber = num_to_asn1integer(num, rev->serialNumber);
+
+ return num;
+}
+
+static VALUE
+ossl_x509revoked_get_time(VALUE self)
+{
+ X509_REVOKED *rev;
+
+ GetX509Rev(self, rev);
+
+ return asn1time_to_time(rev->revocationDate);
+}
+
+static VALUE
+ossl_x509revoked_set_time(VALUE self, VALUE time)
+{
+ X509_REVOKED *rev;
+ time_t sec;
+
+ sec = time_to_time_t(time);
+ GetX509Rev(self, rev);
+ if (!X509_time_adj(rev->revocationDate, 0, &sec)) {
+ ossl_raise(eX509RevError, NULL);
+ }
+
+ return time;
+}
+/*
+ * Gets X509v3 extensions as array of X509Ext objects
+ */
+static VALUE
+ossl_x509revoked_get_extensions(VALUE self)
+{
+ X509_REVOKED *rev;
+ int count, i;
+ X509_EXTENSION *ext;
+ VALUE ary;
+
+ GetX509Rev(self, rev);
+ count = X509_REVOKED_get_ext_count(rev);
+ if (count < 0) {
+ OSSL_Debug("count < 0???");
+ return rb_ary_new();
+ }
+ ary = rb_ary_new2(count);
+ for (i=0; i<count; i++) {
+ ext = X509_REVOKED_get_ext(rev, i);
+ rb_ary_push(ary, ossl_x509ext_new(ext));
+ }
+
+ return ary;
+}
+
+/*
+ * Sets X509_EXTENSIONs
+ */
+static VALUE
+ossl_x509revoked_set_extensions(VALUE self, VALUE ary)
+{
+ X509_REVOKED *rev;
+ X509_EXTENSION *ext;
+ int i;
+ VALUE item;
+
+ Check_Type(ary, T_ARRAY);
+ for (i=0; i<RARRAY(ary)->len; i++) {
+ OSSL_Check_Kind(RARRAY(ary)->ptr[i], cX509Ext);
+ }
+ GetX509Rev(self, rev);
+ sk_X509_EXTENSION_pop_free(rev->extensions, X509_EXTENSION_free);
+ rev->extensions = NULL;
+ for (i=0; i<RARRAY(ary)->len; i++) {
+ item = RARRAY(ary)->ptr[i];
+ ext = DupX509ExtPtr(item);
+ if(!X509_REVOKED_add_ext(rev, ext, -1)) {
+ ossl_raise(eX509RevError, NULL);
+ }
+ }
+
+ return ary;
+}
+
+static VALUE
+ossl_x509revoked_add_extension(VALUE self, VALUE ext)
+{
+ X509_REVOKED *rev;
+
+ GetX509Rev(self, rev);
+ if(!X509_REVOKED_add_ext(rev, DupX509ExtPtr(ext), -1)) {
+ ossl_raise(eX509RevError, NULL);
+ }
+
+ return ext;
+}
+
+/*
+ * INIT
+ */
+void
+Init_ossl_x509revoked()
+{
+ eX509RevError = rb_define_class_under(mX509, "RevokedError", eOSSLError);
+
+ cX509Rev = rb_define_class_under(mX509, "Revoked", rb_cObject);
+
+ rb_define_alloc_func(cX509Rev, ossl_x509revoked_alloc);
+ rb_define_method(cX509Rev, "initialize", ossl_x509revoked_initialize, -1);
+
+ rb_define_method(cX509Rev, "serial", ossl_x509revoked_get_serial, 0);
+ rb_define_method(cX509Rev, "serial=", ossl_x509revoked_set_serial, 1);
+ rb_define_method(cX509Rev, "time", ossl_x509revoked_get_time, 0);
+ rb_define_method(cX509Rev, "time=", ossl_x509revoked_set_time, 1);
+ rb_define_method(cX509Rev, "extensions", ossl_x509revoked_get_extensions, 0);
+ rb_define_method(cX509Rev, "extensions=", ossl_x509revoked_set_extensions, 1);
+ rb_define_method(cX509Rev, "add_extension", ossl_x509revoked_add_extension, 1);
+}
+
diff --git a/ruby_1_8_5/ext/openssl/ossl_x509store.c b/ruby_1_8_5/ext/openssl/ossl_x509store.c
new file mode 100644
index 0000000000..360769e612
--- /dev/null
+++ b/ruby_1_8_5/ext/openssl/ossl_x509store.c
@@ -0,0 +1,613 @@
+/*
+ * $Id: ossl_x509store.c,v 1.2.2.5 2005/09/10 00:54:29 gotoyuzo Exp $
+ * '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'.)
+ */
+#include "ossl.h"
+#include <rubysig.h>
+
+#define WrapX509Store(klass, obj, st) do { \
+ if (!st) { \
+ ossl_raise(rb_eRuntimeError, "STORE wasn't initialized!"); \
+ } \
+ obj = Data_Wrap_Struct(klass, 0, X509_STORE_free, st); \
+} while (0)
+#define GetX509Store(obj, st) do { \
+ Data_Get_Struct(obj, X509_STORE, st); \
+ if (!st) { \
+ ossl_raise(rb_eRuntimeError, "STORE wasn't initialized!"); \
+ } \
+} while (0)
+#define SafeGetX509Store(obj, st) do { \
+ OSSL_Check_Kind(obj, cX509Store); \
+ GetX509Store(obj, st); \
+} while (0)
+
+#define WrapX509StCtx(klass, obj, ctx) do { \
+ if (!ctx) { \
+ ossl_raise(rb_eRuntimeError, "STORE_CTX wasn't initialized!"); \
+ } \
+ obj = Data_Wrap_Struct(klass, 0, ossl_x509stctx_free, ctx); \
+} while (0)
+#define GetX509StCtx(obj, ctx) do { \
+ Data_Get_Struct(obj, X509_STORE_CTX, ctx); \
+ if (!ctx) { \
+ ossl_raise(rb_eRuntimeError, "STORE_CTX is out of scope!"); \
+ } \
+} while (0)
+#define SafeGetX509StCtx(obj, storep) do { \
+ OSSL_Check_Kind(obj, cX509StoreContext); \
+ GetX509Store(obj, ctx); \
+} while (0)
+
+/*
+ * Classes
+ */
+VALUE cX509Store;
+VALUE cX509StoreContext;
+VALUE eX509StoreError;
+
+/*
+ * Public functions
+ */
+VALUE
+ossl_x509store_new(X509_STORE *store)
+{
+ VALUE obj;
+
+ WrapX509Store(cX509Store, obj, store);
+
+ return obj;
+}
+
+X509_STORE *
+GetX509StorePtr(VALUE obj)
+{
+ X509_STORE *store;
+
+ SafeGetX509Store(obj, store);
+
+ return store;
+}
+
+X509_STORE *
+DupX509StorePtr(VALUE obj)
+{
+ X509_STORE *store;
+
+ SafeGetX509Store(obj, store);
+ CRYPTO_add(&store->references, 1, CRYPTO_LOCK_X509_STORE);
+
+ return store;
+}
+
+/*
+ * Private functions
+ */
+static VALUE
+ossl_x509store_alloc(VALUE klass)
+{
+ X509_STORE *store;
+ VALUE obj;
+
+ if((store = X509_STORE_new()) == NULL){
+ ossl_raise(eX509StoreError, NULL);
+ }
+ WrapX509Store(klass, obj, store);
+
+ return obj;
+}
+
+/*
+ * General callback for OpenSSL verify
+ */
+static VALUE
+ossl_x509store_set_vfy_cb(VALUE self, VALUE cb)
+{
+ X509_STORE *store;
+
+ GetX509Store(self, store);
+ X509_STORE_set_ex_data(store, ossl_verify_cb_idx, (void*)cb);
+ rb_iv_set(self, "@verify_callback", cb);
+
+ return cb;
+}
+
+static VALUE
+ossl_x509store_initialize(int argc, VALUE *argv, VALUE self)
+{
+ X509_STORE *store;
+
+ GetX509Store(self, store);
+ X509_STORE_set_verify_cb_func(store, ossl_verify_cb);
+ ossl_x509store_set_vfy_cb(self, Qnil);
+
+#if (OPENSSL_VERSION_NUMBER < 0x00907000L)
+ rb_iv_set(self, "@flags", INT2NUM(0));
+ rb_iv_set(self, "@purpose", INT2NUM(0));
+ rb_iv_set(self, "@trust", INT2NUM(0));
+#endif
+
+ /* last verification status */
+ rb_iv_set(self, "@error", Qnil);
+ rb_iv_set(self, "@error_string", Qnil);
+ rb_iv_set(self, "@chain", Qnil);
+ rb_iv_set(self, "@time", Qnil);
+
+ return self;
+}
+
+static VALUE
+ossl_x509store_set_flags(VALUE self, VALUE flags)
+{
+#if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
+ X509_STORE *store;
+ long f = NUM2LONG(flags);
+
+ GetX509Store(self, store);
+ X509_STORE_set_flags(store, f);
+#else
+ rb_iv_set(self, "@flags", flags);
+#endif
+
+ return flags;
+}
+
+static VALUE
+ossl_x509store_set_purpose(VALUE self, VALUE purpose)
+{
+#if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
+ X509_STORE *store;
+ long p = NUM2LONG(purpose);
+
+ GetX509Store(self, store);
+ X509_STORE_set_purpose(store, p);
+#else
+ rb_iv_set(self, "@purpose", purpose);
+#endif
+
+ return purpose;
+}
+
+static VALUE
+ossl_x509store_set_trust(VALUE self, VALUE trust)
+{
+#if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
+ X509_STORE *store;
+ long t = NUM2LONG(trust);
+
+ GetX509Store(self, store);
+ X509_STORE_set_trust(store, t);
+#else
+ rb_iv_set(self, "@trust", trust);
+#endif
+
+ return trust;
+}
+
+static VALUE
+ossl_x509store_set_time(VALUE self, VALUE time)
+{
+ rb_iv_set(self, "@time", time);
+ return time;
+}
+
+static VALUE
+ossl_x509store_add_file(VALUE self, VALUE file)
+{
+ X509_STORE *store;
+ X509_LOOKUP *lookup;
+ char *path = NULL;
+
+ if(file != Qnil){
+ Check_SafeStr(file);
+ path = RSTRING(file)->ptr;
+ }
+ GetX509Store(self, store);
+ lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
+ if(lookup == NULL) ossl_raise(eX509StoreError, NULL);
+ if(X509_LOOKUP_load_file(lookup, path, X509_FILETYPE_PEM) != 1){
+ ossl_raise(eX509StoreError, NULL);
+ }
+
+ return self;
+}
+
+static VALUE
+ossl_x509store_add_path(VALUE self, VALUE dir)
+{
+ X509_STORE *store;
+ X509_LOOKUP *lookup;
+ char *path = NULL;
+
+ if(dir != Qnil){
+ Check_SafeStr(dir);
+ path = RSTRING(dir)->ptr;
+ }
+ GetX509Store(self, store);
+ lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir());
+ if(lookup == NULL) ossl_raise(eX509StoreError, NULL);
+ if(X509_LOOKUP_add_dir(lookup, path, X509_FILETYPE_PEM) != 1){
+ ossl_raise(eX509StoreError, NULL);
+ }
+
+ return self;
+}
+
+static VALUE
+ossl_x509store_set_default_paths(VALUE self)
+{
+ X509_STORE *store;
+
+ GetX509Store(self, store);
+ if (X509_STORE_set_default_paths(store) != 1){
+ ossl_raise(eX509StoreError, NULL);
+ }
+
+ return Qnil;
+}
+
+static VALUE
+ossl_x509store_add_cert(VALUE self, VALUE arg)
+{
+ X509_STORE *store;
+ X509 *cert;
+
+ cert = GetX509CertPtr(arg); /* NO NEED TO DUP */
+ GetX509Store(self, store);
+ if (X509_STORE_add_cert(store, cert) != 1){
+ ossl_raise(eX509StoreError, NULL);
+ }
+
+ return self;
+}
+
+static VALUE
+ossl_x509store_add_crl(VALUE self, VALUE arg)
+{
+ X509_STORE *store;
+ X509_CRL *crl;
+
+ crl = GetX509CRLPtr(arg); /* NO NEED TO DUP */
+ GetX509Store(self, store);
+ if (X509_STORE_add_crl(store, crl) != 1){
+ ossl_raise(eX509StoreError, NULL);
+ }
+
+ return self;
+}
+
+static VALUE ossl_x509stctx_get_err(VALUE);
+static VALUE ossl_x509stctx_get_err_string(VALUE);
+static VALUE ossl_x509stctx_get_chain(VALUE);
+
+static VALUE
+ossl_x509store_verify(int argc, VALUE *argv, VALUE self)
+{
+ VALUE cert, chain;
+ VALUE ctx, proc, result;
+
+ rb_scan_args(argc, argv, "11", &cert, &chain);
+ ctx = rb_funcall(cX509StoreContext, rb_intern("new"), 3, self, cert, chain);
+ proc = rb_block_given_p() ? rb_block_proc() :
+ rb_iv_get(self, "@verify_callback");
+ rb_iv_set(ctx, "@verify_callback", proc);
+ result = rb_funcall(ctx, rb_intern("verify"), 0);
+
+ rb_iv_set(self, "@error", ossl_x509stctx_get_err(ctx));
+ rb_iv_set(self, "@error_string", ossl_x509stctx_get_err_string(ctx));
+ rb_iv_set(self, "@chain", ossl_x509stctx_get_chain(ctx));
+
+ return result;
+}
+
+/*
+ * Public Functions
+ */
+static void ossl_x509stctx_free(X509_STORE_CTX*);
+
+VALUE
+ossl_x509stctx_new(X509_STORE_CTX *ctx)
+{
+ VALUE obj;
+
+ WrapX509StCtx(cX509StoreContext, obj, ctx);
+
+ return obj;
+}
+
+VALUE
+ossl_x509stctx_clear_ptr(VALUE obj)
+{
+ OSSL_Check_Kind(obj, cX509StoreContext);
+ RDATA(obj)->data = NULL;
+
+ return obj;
+}
+
+/*
+ * Private functions
+ */
+static void
+ossl_x509stctx_free(X509_STORE_CTX *ctx)
+{
+ if(ctx->untrusted)
+ sk_X509_pop_free(ctx->untrusted, X509_free);
+ if(ctx->cert)
+ X509_free(ctx->cert);
+ X509_STORE_CTX_free(ctx);
+}
+
+static VALUE
+ossl_x509stctx_alloc(VALUE klass)
+{
+ X509_STORE_CTX *ctx;
+ VALUE obj;
+
+ if((ctx = X509_STORE_CTX_new()) == NULL){
+ ossl_raise(eX509StoreError, NULL);
+ }
+ WrapX509StCtx(klass, obj, ctx);
+
+ return obj;
+}
+
+static VALUE ossl_x509stctx_set_flags(VALUE, VALUE);
+static VALUE ossl_x509stctx_set_purpose(VALUE, VALUE);
+static VALUE ossl_x509stctx_set_trust(VALUE, VALUE);
+static VALUE ossl_x509stctx_set_time(VALUE, VALUE);
+
+static VALUE
+ossl_x509stctx_initialize(int argc, VALUE *argv, VALUE self)
+{
+ VALUE store, cert, chain, t;
+ X509_STORE_CTX *ctx;
+ X509_STORE *x509st;
+ X509 *x509 = NULL;
+ STACK_OF(X509) *x509s = NULL;
+
+ rb_scan_args(argc, argv, "12", &store, &cert, &chain);
+ GetX509StCtx(self, ctx);
+ SafeGetX509Store(store, x509st);
+ if(!NIL_P(cert)) x509 = DupX509CertPtr(cert); /* NEED TO DUP */
+ if(!NIL_P(chain)) x509s = ossl_x509_ary2sk(chain);
+#if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
+ if(X509_STORE_CTX_init(ctx, x509st, x509, x509s) != 1){
+ sk_X509_pop_free(x509s, X509_free);
+ ossl_raise(eX509StoreError, NULL);
+ }
+#else
+ X509_STORE_CTX_init(ctx, x509st, x509, x509s);
+ ossl_x509stctx_set_flags(self, rb_iv_get(store, "@flags"));
+ ossl_x509stctx_set_purpose(self, rb_iv_get(store, "@purpose"));
+ ossl_x509stctx_set_trust(self, rb_iv_get(store, "@trust"));
+#endif
+ if (!NIL_P(t = rb_iv_get(store, "@time")))
+ ossl_x509stctx_set_time(self, t);
+ rb_iv_set(self, "@verify_callback", rb_iv_get(store, "@verify_callback"));
+ rb_iv_set(self, "@cert", cert);
+
+ return self;
+}
+
+static VALUE
+ossl_x509stctx_verify(VALUE self)
+{
+ X509_STORE_CTX *ctx;
+ int result;
+
+ GetX509StCtx(self, ctx);
+ X509_STORE_CTX_set_ex_data(ctx, ossl_verify_cb_idx,
+ (void*)rb_iv_get(self, "@verify_callback"));
+ result = X509_verify_cert(ctx);
+
+ return result ? Qtrue : Qfalse;
+}
+
+static VALUE
+ossl_x509stctx_get_chain(VALUE self)
+{
+ X509_STORE_CTX *ctx;
+ STACK_OF(X509) *chain;
+ X509 *x509;
+ int i, num;
+ VALUE ary;
+
+ GetX509StCtx(self, ctx);
+ if((chain = X509_STORE_CTX_get_chain(ctx)) == NULL){
+ return Qnil;
+ }
+ if((num = sk_X509_num(chain)) < 0){
+ OSSL_Debug("certs in chain < 0???");
+ return rb_ary_new();
+ }
+ ary = rb_ary_new2(num);
+ for(i = 0; i < num; i++) {
+ x509 = sk_X509_value(chain, i);
+ rb_ary_push(ary, ossl_x509_new(x509));
+ }
+
+ return ary;
+}
+
+static VALUE
+ossl_x509stctx_get_err(VALUE self)
+{
+ X509_STORE_CTX *ctx;
+
+ GetX509StCtx(self, ctx);
+
+ return INT2FIX(X509_STORE_CTX_get_error(ctx));
+}
+
+static VALUE
+ossl_x509stctx_set_error(VALUE self, VALUE err)
+{
+ X509_STORE_CTX *ctx;
+
+ GetX509StCtx(self, ctx);
+ X509_STORE_CTX_set_error(ctx, FIX2INT(err));
+
+ return err;
+}
+
+static VALUE
+ossl_x509stctx_get_err_string(VALUE self)
+{
+ X509_STORE_CTX *ctx;
+ long err;
+
+ GetX509StCtx(self, ctx);
+ err = X509_STORE_CTX_get_error(ctx);
+
+ return rb_str_new2(X509_verify_cert_error_string(err));
+}
+
+static VALUE
+ossl_x509stctx_get_err_depth(VALUE self)
+{
+ X509_STORE_CTX *ctx;
+
+ GetX509StCtx(self, ctx);
+
+ return INT2FIX(X509_STORE_CTX_get_error_depth(ctx));
+}
+
+static VALUE
+ossl_x509stctx_get_curr_cert(VALUE self)
+{
+ X509_STORE_CTX *ctx;
+
+ GetX509StCtx(self, ctx);
+
+ return ossl_x509_new(X509_STORE_CTX_get_current_cert(ctx));
+}
+
+static VALUE
+ossl_x509stctx_get_curr_crl(VALUE self)
+{
+#if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
+ X509_STORE_CTX *ctx;
+
+ GetX509StCtx(self, ctx);
+ if(!ctx->current_crl) return Qnil;
+
+ return ossl_x509crl_new(ctx->current_crl);
+#else
+ return Qnil;
+#endif
+}
+
+static VALUE
+ossl_x509stctx_cleanup(VALUE self)
+{
+ X509_STORE_CTX *ctx;
+
+ GetX509StCtx(self, ctx);
+ X509_STORE_CTX_cleanup(ctx);
+
+ return self;
+}
+
+static VALUE
+ossl_x509stctx_set_flags(VALUE self, VALUE flags)
+{
+ X509_STORE_CTX *store;
+ long f = NUM2LONG(flags);
+
+ GetX509StCtx(self, store);
+ X509_STORE_CTX_set_flags(store, f);
+
+ return flags;
+}
+
+static VALUE
+ossl_x509stctx_set_purpose(VALUE self, VALUE purpose)
+{
+ X509_STORE_CTX *store;
+ long p = NUM2LONG(purpose);
+
+ GetX509StCtx(self, store);
+ X509_STORE_CTX_set_purpose(store, p);
+
+ return purpose;
+}
+
+static VALUE
+ossl_x509stctx_set_trust(VALUE self, VALUE trust)
+{
+ X509_STORE_CTX *store;
+ long t = NUM2LONG(trust);
+
+ GetX509StCtx(self, store);
+ X509_STORE_CTX_set_trust(store, t);
+
+ return trust;
+}
+
+static VALUE
+ossl_x509stctx_set_time(VALUE self, VALUE time)
+{
+ X509_STORE_CTX *store;
+ long t;
+
+ t = NUM2LONG(rb_Integer(time));
+ GetX509StCtx(self, store);
+ X509_STORE_CTX_set_time(store, 0, t);
+
+ return time;
+}
+
+/*
+ * INIT
+ */
+void
+Init_ossl_x509store()
+{
+ VALUE x509stctx;
+
+ eX509StoreError = rb_define_class_under(mX509, "StoreError", eOSSLError);
+
+ cX509Store = rb_define_class_under(mX509, "Store", rb_cObject);
+ rb_attr(cX509Store, rb_intern("verify_callback"), 1, 0, Qfalse);
+ rb_attr(cX509Store, rb_intern("error"), 1, 0, Qfalse);
+ rb_attr(cX509Store, rb_intern("error_string"), 1, 0, Qfalse);
+ rb_attr(cX509Store, rb_intern("chain"), 1, 0, Qfalse);
+ rb_define_alloc_func(cX509Store, ossl_x509store_alloc);
+ rb_define_method(cX509Store, "initialize", ossl_x509store_initialize, -1);
+ rb_define_method(cX509Store, "verify_callback=", ossl_x509store_set_vfy_cb, 1);
+ rb_define_method(cX509Store, "flags=", ossl_x509store_set_flags, 1);
+ rb_define_method(cX509Store, "purpose=", ossl_x509store_set_purpose, 1);
+ rb_define_method(cX509Store, "trust=", ossl_x509store_set_trust, 1);
+ rb_define_method(cX509Store, "time=", ossl_x509store_set_time, 1);
+ rb_define_method(cX509Store, "add_path", ossl_x509store_add_path, 1);
+ rb_define_method(cX509Store, "add_file", ossl_x509store_add_file, 1);
+ rb_define_method(cX509Store, "set_default_paths", ossl_x509store_set_default_paths, 0);
+ rb_define_method(cX509Store, "add_cert", ossl_x509store_add_cert, 1);
+ rb_define_method(cX509Store, "add_crl", ossl_x509store_add_crl, 1);
+ rb_define_method(cX509Store, "verify", ossl_x509store_verify, -1);
+
+ cX509StoreContext = rb_define_class_under(mX509,"StoreContext",rb_cObject);
+ x509stctx = cX509StoreContext;
+ rb_define_alloc_func(cX509StoreContext, ossl_x509stctx_alloc);
+ rb_define_method(x509stctx,"initialize", ossl_x509stctx_initialize, -1);
+ rb_define_method(x509stctx,"verify", ossl_x509stctx_verify, 0);
+ rb_define_method(x509stctx,"chain", ossl_x509stctx_get_chain,0);
+ rb_define_method(x509stctx,"error", ossl_x509stctx_get_err, 0);
+ rb_define_method(x509stctx,"error=", ossl_x509stctx_set_error, 1);
+ rb_define_method(x509stctx,"error_string",ossl_x509stctx_get_err_string,0);
+ rb_define_method(x509stctx,"error_depth", ossl_x509stctx_get_err_depth, 0);
+ rb_define_method(x509stctx,"current_cert",ossl_x509stctx_get_curr_cert, 0);
+ rb_define_method(x509stctx,"current_crl", ossl_x509stctx_get_curr_crl, 0);
+ rb_define_method(x509stctx,"cleanup", ossl_x509stctx_cleanup, 0);
+ rb_define_method(x509stctx,"flags=", ossl_x509stctx_set_flags, 1);
+ rb_define_method(x509stctx,"purpose=", ossl_x509stctx_set_purpose, 1);
+ rb_define_method(x509stctx,"trust=", ossl_x509stctx_set_trust, 1);
+ rb_define_method(x509stctx,"time=", ossl_x509stctx_set_time, 1);
+
+}
diff --git a/ruby_1_8_5/ext/openssl/ruby_missing.h b/ruby_1_8_5/ext/openssl/ruby_missing.h
new file mode 100644
index 0000000000..f673bb157a
--- /dev/null
+++ b/ruby_1_8_5/ext/openssl/ruby_missing.h
@@ -0,0 +1,18 @@
+/*
+ * $Id: ruby_missing.h,v 1.3 2003/09/06 08:56:57 gotoyuzo Exp $
+ * 'OpenSSL for Ruby' project
+ * Copyright (C) 2001-2003 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_RUBY_MISSING_H_)
+#define _OSS_RUBY_MISSING_H_
+
+#define rb_define_copy_func(klass, func) \
+ rb_define_method(klass, "initialize_copy", func, 1)
+
+#endif /* _OSS_RUBY_MISSING_H_ */
+