Skip to content

Commit

Permalink
Showing 164 changed files with 27,391 additions and 535 deletions.
Original file line number Diff line number Diff line change
@@ -33,7 +33,12 @@ public JavaInternalBlockBody(Ruby runtime, ThreadContext originalContext, String
this.methodName = methodName;
this.dummyScope = runtime.getStaticScopeFactory().getDummyScope();
}


@Deprecated // needed by jruby-rack until it supports 1.7 along side with 9K
public JavaInternalBlockBody(Ruby runtime, Arity arity) {
this(runtime, null, null, Signature.from(arity));
}

// Make sure we are still on the same thread as originator if we care
private void threadCheck(ThreadContext yieldingContext) {
if (originalContext != null && yieldingContext != originalContext) {
2 changes: 2 additions & 0 deletions lib/ruby/truffle/README.md
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
pr-zlib is version 1.0.3, commit c1418dd1abde5c4f6bcc7073b7965eeb4c168144
openssl is from MRI 2.3.1
openssl/openssl.rb has been modified to refer to 'openssl/openssl'
4 changes: 2 additions & 2 deletions lib/ruby/truffle/cext/ruby.h
Original file line number Diff line number Diff line change
@@ -34,7 +34,7 @@ extern "C" {
typedef void* ID;
typedef void* VALUE;

#define NORETURN __attribute__((__noreturn__))
#define NORETURN(X) __attribute__((__noreturn__)) X

// Constants

@@ -175,7 +175,7 @@ void rb_define_global_const(const char *name, VALUE value);

// Raising exceptions

NORETURN void rb_raise(VALUE exception, const char *format, ...);
NORETURN(void rb_raise(VALUE exception, const char *format, ...));

// Defining classes, modules and methods

Empty file.
Empty file added lib/ruby/truffle/cext/ruby/io.h
Empty file.
Empty file.
Empty file.
21 changes: 21 additions & 0 deletions lib/ruby/truffle/openssl/openssl.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# frozen_string_literal: false
=begin
= Info
'OpenSSL for Ruby 2' project
Copyright (C) 2002 Michal Rokos <m.rokos@sh.cvut.cz>
All rights reserved.
= Licence
This program is licensed under the same licence as Ruby.
(See the file 'LICENCE'.)
=end

require 'openssl.so'

require 'openssl/bn'
require 'openssl/pkey'
require 'openssl/cipher'
require 'openssl/config'
require 'openssl/digest'
require 'openssl/x509'
require 'openssl/ssl'
39 changes: 39 additions & 0 deletions lib/ruby/truffle/openssl/openssl/bn.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# frozen_string_literal: false
#--
#
# = 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 licensed under the same licence as Ruby.
# (See the file 'LICENCE'.)
#++

module OpenSSL
class BN
include Comparable

def pretty_print(q)
q.object_group(self) {
q.text ' '
q.text to_i.to_s
}
end
end # BN
end # OpenSSL

##
# Add double dispatch to Integer
#
class Integer
# Casts an Integer as an OpenSSL::BN
#
# See `man bn` for more info.
def to_bn
OpenSSL::BN::new(self)
end
end # Integer
451 changes: 451 additions & 0 deletions lib/ruby/truffle/openssl/openssl/buffering.rb

Large diffs are not rendered by default.

59 changes: 59 additions & 0 deletions lib/ruby/truffle/openssl/openssl/cipher.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# frozen_string_literal: false
#--
# = 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 licensed under the same licence as Ruby.
# (See the file 'LICENCE'.)
#++

module OpenSSL
class 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)
}

# Generate, set, and return a random key.
# You must call cipher.encrypt or cipher.decrypt before calling this method.
def random_key
str = OpenSSL::Random.random_bytes(self.key_len)
self.key = str
return str
end

# Generate, set, and return a random iv.
# You must call cipher.encrypt or cipher.decrypt before calling this method.
def random_iv
str = OpenSSL::Random.random_bytes(self.iv_len)
self.iv = str
return str
end

# This class is only provided for backwards compatibility. Use OpenSSL::Cipher in the future.
class Cipher < Cipher
# add warning
end
end # Cipher
end # OpenSSL
473 changes: 473 additions & 0 deletions lib/ruby/truffle/openssl/openssl/config.rb

Large diffs are not rendered by default.

84 changes: 84 additions & 0 deletions lib/ruby/truffle/openssl/openssl/digest.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# frozen_string_literal: false
#--
# = 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 licensed under the same licence as Ruby.
# (See the file 'LICENCE'.)
#++

module OpenSSL
class Digest

alg = %w(MD2 MD4 MD5 MDC2 RIPEMD160 SHA1)
if OPENSSL_VERSION_NUMBER < 0x10100000
alg += %w(DSS DSS1 SHA)
end
if OPENSSL_VERSION_NUMBER > 0x00908000
alg += %w(SHA224 SHA256 SHA384 SHA512)
end

# Return the +data+ hash computed with +name+ Digest. +name+ is either the
# long name or short name of a supported digest algorithm.
#
# === Examples
#
# OpenSSL::Digest.digest("SHA256", "abc")
#
# which is equivalent to:
#
# OpenSSL::Digest::SHA256.digest("abc")

def self.digest(name, data)
super(data, name)
end

alg.each{|name|
klass = Class.new(self) {
define_method(:initialize, ->(data = nil) {super(name, data)})
}
singleton = (class << klass; self; end)
singleton.class_eval{
define_method(:digest){|data| new.digest(data) }
define_method(:hexdigest){|data| new.hexdigest(data) }
}
const_set(name, klass)
}

# Deprecated.
#
# This class is only provided for backwards compatibility.
class Digest < Digest # :nodoc:
# Deprecated.
#
# See OpenSSL::Digest.new
def initialize(*args)
warn('Digest::Digest is deprecated; use Digest')
super(*args)
end
end

end # Digest

# Returns a Digest subclass by +name+.
#
# require 'openssl'
#
# OpenSSL::Digest("MD5")
# # => OpenSSL::Digest::MD5
#
# Digest("Foo")
# # => NameError: wrong constant name Foo

def Digest(name)
OpenSSL::Digest.const_get(name)
end

module_function :Digest

end # OpenSSL
41 changes: 41 additions & 0 deletions lib/ruby/truffle/openssl/openssl/pkey.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# frozen_string_literal: false
module OpenSSL
module PKey
if defined?(OpenSSL::PKey::DH)

class DH
DEFAULT_1024 = new <<-_end_of_pem_
-----BEGIN DH PARAMETERS-----
MIGHAoGBAJ0lOVy0VIr/JebWn0zDwY2h+rqITFOpdNr6ugsgvkDXuucdcChhYExJ
AV/ZD2AWPbrTqV76mGRgJg4EddgT1zG0jq3rnFdMj2XzkBYx3BVvfR0Arnby0RHR
T4h7KZ/2zmjvV+eF8kBUHBJAojUlzxKj4QeO2x20FP9X5xmNUXeDAgEC
-----END DH PARAMETERS-----
_end_of_pem_

DEFAULT_2048 = new <<-_end_of_pem_
-----BEGIN DH PARAMETERS-----
MIIBCAKCAQEA7E6kBrYiyvmKAMzQ7i8WvwVk9Y/+f8S7sCTN712KkK3cqd1jhJDY
JbrYeNV3kUIKhPxWHhObHKpD1R84UpL+s2b55+iMd6GmL7OYmNIT/FccKhTcveab
VBmZT86BZKYyf45hUF9FOuUM9xPzuK3Vd8oJQvfYMCd7LPC0taAEljQLR4Edf8E6
YoaOffgTf5qxiwkjnlVZQc3whgnEt9FpVMvQ9eknyeGB5KHfayAc3+hUAvI3/Cr3
1bNveX5wInh5GDx1FGhKBZ+s1H+aedudCm7sCgRwv8lKWYGiHzObSma8A86KG+MD
7Lo5JquQ3DlBodj3IDyPrxIv96lvRPFtAwIBAg==
-----END DH PARAMETERS-----
_end_of_pem_
end

DEFAULT_TMP_DH_CALLBACK = lambda { |ctx, is_export, keylen|
warn "using default DH parameters." if $VERBOSE
case keylen
when 1024 then OpenSSL::PKey::DH::DEFAULT_1024
when 2048 then OpenSSL::PKey::DH::DEFAULT_2048
else
nil
end
}

else
DEFAULT_TMP_DH_CALLBACK = nil
end
end
end
390 changes: 390 additions & 0 deletions lib/ruby/truffle/openssl/openssl/ssl.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,390 @@
# frozen_string_literal: false
=begin
= Info
'OpenSSL for Ruby 2' project
Copyright (C) 2001 GOTOU YUUZOU <gotoyuzo@notwork.org>
All rights reserved.
= Licence
This program is licensed under the same licence as Ruby.
(See the file 'LICENCE'.)
=end

require "openssl/buffering"
require "io/nonblock"

module OpenSSL
module SSL
class SSLContext
DEFAULT_PARAMS = {
:ssl_version => "SSLv23",
:verify_mode => OpenSSL::SSL::VERIFY_PEER,
:ciphers => %w{
ECDHE-ECDSA-AES128-GCM-SHA256
ECDHE-RSA-AES128-GCM-SHA256
ECDHE-ECDSA-AES256-GCM-SHA384
ECDHE-RSA-AES256-GCM-SHA384
DHE-RSA-AES128-GCM-SHA256
DHE-DSS-AES128-GCM-SHA256
DHE-RSA-AES256-GCM-SHA384
DHE-DSS-AES256-GCM-SHA384
ECDHE-ECDSA-AES128-SHA256
ECDHE-RSA-AES128-SHA256
ECDHE-ECDSA-AES128-SHA
ECDHE-RSA-AES128-SHA
ECDHE-ECDSA-AES256-SHA384
ECDHE-RSA-AES256-SHA384
ECDHE-ECDSA-AES256-SHA
ECDHE-RSA-AES256-SHA
DHE-RSA-AES128-SHA256
DHE-RSA-AES256-SHA256
DHE-RSA-AES128-SHA
DHE-RSA-AES256-SHA
DHE-DSS-AES128-SHA256
DHE-DSS-AES256-SHA256
DHE-DSS-AES128-SHA
DHE-DSS-AES256-SHA
AES128-GCM-SHA256
AES256-GCM-SHA384
AES128-SHA256
AES256-SHA256
AES128-SHA
AES256-SHA
ECDHE-ECDSA-RC4-SHA
ECDHE-RSA-RC4-SHA
RC4-SHA
}.join(":"),
:options => -> {
opts = OpenSSL::SSL::OP_ALL
opts &= ~OpenSSL::SSL::OP_DONT_INSERT_EMPTY_FRAGMENTS
opts |= OpenSSL::SSL::OP_NO_COMPRESSION if defined?(OpenSSL::SSL::OP_NO_COMPRESSION)
opts |= OpenSSL::SSL::OP_NO_SSLv2 | OpenSSL::SSL::OP_NO_SSLv3
opts
}.call
}

DEFAULT_CERT_STORE = OpenSSL::X509::Store.new
DEFAULT_CERT_STORE.set_default_paths
DEFAULT_CERT_STORE.flags = OpenSSL::X509::V_FLAG_CRL_CHECK_ALL

INIT_VARS = ["cert", "key", "client_ca", "ca_file", "ca_path",
"timeout", "verify_mode", "verify_depth", "renegotiation_cb",
"verify_callback", "cert_store", "extra_chain_cert",
"client_cert_cb", "session_id_context", "tmp_dh_callback",
"session_get_cb", "session_new_cb", "session_remove_cb",
"tmp_ecdh_callback", "servername_cb", "npn_protocols",
"alpn_protocols", "alpn_select_cb",
"npn_select_cb"].map { |x| "@#{x}" }

# A callback invoked when DH parameters are required.
#
# The callback is invoked with the Session for the key exchange, an
# flag indicating the use of an export cipher and the keylength
# required.
#
# The callback must return an OpenSSL::PKey::DH instance of the correct
# key length.

attr_accessor :tmp_dh_callback

if ExtConfig::HAVE_TLSEXT_HOST_NAME
# A callback invoked at connect time to distinguish between multiple
# server names.
#
# The callback is invoked with an SSLSocket and a server name. The
# callback must return an SSLContext for the server name or nil.
attr_accessor :servername_cb
end

# call-seq:
# SSLContext.new => ctx
# SSLContext.new(:TLSv1) => ctx
# SSLContext.new("SSLv23_client") => ctx
#
# You can get a list of valid methods with OpenSSL::SSL::SSLContext::METHODS
def initialize(version = nil)
INIT_VARS.each { |v| instance_variable_set v, nil }
self.options = self.options | OpenSSL::SSL::OP_ALL
return unless version
self.ssl_version = version
end

##
# Sets the parameters for this SSL context to the values in +params+.
# The keys in +params+ must be assignment methods on SSLContext.
#
# If the verify_mode is not VERIFY_NONE and ca_file, ca_path and
# cert_store are not set then the system default certificate store is
# used.

def set_params(params={})
params = DEFAULT_PARAMS.merge(params)
params.each{|name, value| self.__send__("#{name}=", value) }
if self.verify_mode != OpenSSL::SSL::VERIFY_NONE
unless self.ca_file or self.ca_path or self.cert_store
self.cert_store = DEFAULT_CERT_STORE
end
end
return params
end
end

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

def verify_certificate_identity(cert, hostname)
should_verify_common_name = true
cert.extensions.each{|ext|
next if ext.oid != "subjectAltName"
ostr = OpenSSL::ASN1.decode(ext.to_der).value.last
sequence = OpenSSL::ASN1.decode(ostr.value)
sequence.value.each{|san|
case san.tag
when 2 # dNSName in GeneralName (RFC5280)
should_verify_common_name = false
return true if verify_hostname(hostname, san.value)
when 7 # iPAddress in GeneralName (RFC5280)
should_verify_common_name = false
# follows GENERAL_NAME_print() in x509v3/v3_alt.c
if san.value.size == 4
return true if san.value.unpack('C*').join('.') == hostname
elsif san.value.size == 16
return true if san.value.unpack('n*').map { |e| sprintf("%X", e) }.join(':') == hostname
end
end
}
}
if should_verify_common_name
cert.subject.to_a.each{|oid, value|
if oid == "CN"
return true if verify_hostname(hostname, value)
end
}
end
return false
end
module_function :verify_certificate_identity

def verify_hostname(hostname, san) # :nodoc:
# RFC 5280, IA5String is limited to the set of ASCII characters
return false unless san.ascii_only?
return false unless hostname.ascii_only?

# See RFC 6125, section 6.4.1
# Matching is case-insensitive.
san_parts = san.downcase.split(".")

# TODO: this behavior should probably be more strict
return san == hostname if san_parts.size < 2

# Matching is case-insensitive.
host_parts = hostname.downcase.split(".")

# RFC 6125, section 6.4.3, subitem 2.
# If the wildcard character is the only character of the left-most
# label in the presented identifier, the client SHOULD NOT compare
# against anything but the left-most label of the reference
# identifier (e.g., *.example.com would match foo.example.com but
# not bar.foo.example.com or example.com).
return false unless san_parts.size == host_parts.size

# RFC 6125, section 6.4.3, subitem 1.
# The client SHOULD NOT attempt to match a presented identifier in
# which the wildcard character comprises a label other than the
# left-most label (e.g., do not match bar.*.example.net).
return false unless verify_wildcard(host_parts.shift, san_parts.shift)

san_parts.join(".") == host_parts.join(".")
end
module_function :verify_hostname

def verify_wildcard(domain_component, san_component) # :nodoc:
parts = san_component.split("*", -1)

return false if parts.size > 2
return san_component == domain_component if parts.size == 1

# RFC 6125, section 6.4.3, subitem 3.
# The client SHOULD NOT attempt to match a presented identifier
# where the wildcard character is embedded within an A-label or
# U-label of an internationalized domain name.
return false if domain_component.start_with?("xn--") && san_component != "*"

parts[0].length + parts[1].length < domain_component.length &&
domain_component.start_with?(parts[0]) &&
domain_component.end_with?(parts[1])
end
module_function :verify_wildcard

class SSLSocket
include Buffering
include SocketForwarder

if ExtConfig::HAVE_TLSEXT_HOST_NAME
attr_reader :hostname
end

attr_reader :io, :context
attr_accessor :sync_close
alias :to_io :io

# call-seq:
# ssl.sysclose => nil
#
# Sends "close notify" to the peer and tries to shut down the SSL
# connection gracefully.
#
# If sync_close is set to +true+, the underlying IO is also closed.
def sysclose
return if closed?
stop
io.close if sync_close
end

##
# Perform hostname verification after an SSL connection is established
#
# This method MUST be called after calling #connect to ensure that the
# hostname of a remote peer has been verified.
def post_connection_check(hostname)
if peer_cert.nil?
msg = "Peer verification enabled, but no certificate received."
if using_anon_cipher?
msg += " Anonymous cipher suite #{cipher[0]} was negotiated. Anonymous suites must be disabled to use peer verification."
end
raise SSLError, msg
end

unless OpenSSL::SSL.verify_certificate_identity(peer_cert, hostname)
raise SSLError, "hostname \"#{hostname}\" does not match the server certificate"
end
return true
end

def session
SSL::Session.new(self)
rescue SSL::Session::SessionError
nil
end

private

def using_anon_cipher?
ctx = OpenSSL::SSL::SSLContext.new
ctx.ciphers = "aNULL"
ctx.ciphers.include?(cipher)
end

def client_cert_cb
@context.client_cert_cb
end

def tmp_dh_callback
@context.tmp_dh_callback || OpenSSL::PKey::DEFAULT_TMP_DH_CALLBACK
end

def tmp_ecdh_callback
@context.tmp_ecdh_callback
end

def session_new_cb
@context.session_new_cb
end

def session_get_cb
@context.session_get_cb
end
end

##
# SSLServer represents a TCP/IP server socket with Secure Sockets Layer.
class SSLServer
include SocketForwarder
# When true then #accept works exactly the same as TCPServer#accept
attr_accessor :start_immediately

# Creates a new instance of SSLServer.
# * +srv+ is an instance of TCPServer.
# * +ctx+ is an instance of OpenSSL::SSL::SSLContext.
def initialize(svr, ctx)
@svr = svr
@ctx = ctx
unless ctx.session_id_context
# see #6137 - session id may not exceed 32 bytes
prng = ::Random.new($0.hash)
session_id = prng.bytes(16).unpack('H*')[0]
@ctx.session_id_context = session_id
end
@start_immediately = true
end

# Returns the TCPServer passed to the SSLServer when initialized.
def to_io
@svr
end

# See TCPServer#listen for details.
def listen(backlog=5)
@svr.listen(backlog)
end

# See BasicSocket#shutdown for details.
def shutdown(how=Socket::SHUT_RDWR)
@svr.shutdown(how)
end

# Works similar to TCPServer#accept.
def accept
# Socket#accept returns [socket, addrinfo].
# TCPServer#accept returns a socket.
# The following comma strips addrinfo.
sock, = @svr.accept
begin
ssl = OpenSSL::SSL::SSLSocket.new(sock, @ctx)
ssl.sync_close = true
ssl.accept if @start_immediately
ssl
rescue Exception => ex
if ssl
ssl.close
else
sock.close
end
raise ex
end
end

# See IO#close for details.
def close
@svr.close
end
end
end
end
176 changes: 176 additions & 0 deletions lib/ruby/truffle/openssl/openssl/x509.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
# frozen_string_literal: false
#--
# = 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 licensed under the same licence as Ruby.
# (See the file 'LICENCE'.)
#++

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){$&.to_i(16).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)
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

def pretty_print(q)
q.object_group(self) {
q.text ' '
q.text to_s(OpenSSL::X509::Name::RFC2253)
}
end
end

class StoreContext
def cleanup
warn "(#{caller.first}) OpenSSL::X509::StoreContext#cleanup is deprecated with no replacement" if $VERBOSE
end
end

class Certificate
def pretty_print(q)
q.object_group(self) {
q.breakable
q.text 'subject='; q.pp self.subject; q.text ','; q.breakable
q.text 'issuer='; q.pp self.issuer; q.text ','; q.breakable
q.text 'serial='; q.pp self.serial; q.text ','; q.breakable
q.text 'not_before='; q.pp self.not_before; q.text ','; q.breakable
q.text 'not_after='; q.pp self.not_after
}
end
end
end
end
Original file line number Diff line number Diff line change
@@ -172,7 +172,7 @@ def post_match
end

def pre_match
@string.byteslice(0, match.full.at(0)) if @match
@string.byteslice(0, match.byte_begin(0)) if @match
end

def reset_state
@@ -296,7 +296,7 @@ def _scan(pattern, advance_pos, getstr, headonly)

return nil unless @match

fin = @match.full.at(1)
fin = @match.byte_end(0)

@prev_pos = @pos

1 change: 0 additions & 1 deletion lib/ruby/truffle/shims/etc.rb

This file was deleted.

8 changes: 0 additions & 8 deletions maven/jruby-complete/pom.rb
Original file line number Diff line number Diff line change
@@ -10,14 +10,6 @@
inherit "org.jruby:jruby-artifacts:#{version}"
packaging 'bundle'

build do
resource do
directory '${project.basedir}/../..'
includes [ 'BSDL', 'COPYING', 'LEGAL', 'LICENSE.RUBY' ]
target_path '${project.build.outputDirectory}/META-INF/'
end
end

plugin_repository( :id => 'rubygems-releases',
:url => 'https://otto.takari.io/content/repositories/rubygems/maven/releases' )

1 change: 0 additions & 1 deletion spec/truffle/tags/core/array/element_set_tags.txt

This file was deleted.

3 changes: 3 additions & 0 deletions test/truffle/cexts/nokogiri/.jruby-cext-build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
src: $GEM_HOME/gems/nokogiri-1.6.8/ext/nokogiri/*.c
cflags: -I$GEM_HOME/gems/nokogiri-1.6.8/ext/nokogiri `xml2-config --cflags`
out: lib/nokogiri/nokogiri.su
Empty file.
32 changes: 23 additions & 9 deletions tool/jt.rb
Original file line number Diff line number Diff line change
@@ -408,6 +408,7 @@ def help
puts ' USE_SYSTEM_CLANG Use the system clang rather than Sulong\'s when compiling C extensions'
puts ' GRAAL_JS_JAR The location of trufflejs.jar'
puts ' SL_JAR The location of truffle-sl.jar'
puts ' OPENSSL_HOME The location of OpenSSL (the directory containing include etc)'
end

def checkout(branch)
@@ -429,6 +430,11 @@ def build(*options)
mvn env, *maven_options, '-pl', 'truffle', 'package'
when 'cexts'
cextc "#{JRUBY_DIR}/truffle/src/main/c/cext"

#cextc "#{JRUBY_DIR}/truffle/src/main/c/openssl",
# "-I#{ENV['OPENSSL_HOME']}/include",
# '-DRUBY_EXTCONF_H="extconf.h"',
# '-Werror=implicit-function-declaration'
when nil
mvn env, *maven_options, 'package'
else
@@ -543,21 +549,27 @@ def cextc(cext_dir, *clang_opts)
end

config = YAML.load_file(config_file)

config_src = config['src']

if config_src.start_with?('$GEM_HOME/')
src = Dir[ENV['GEM_HOME'] + config_src['$GEM_HOME'.size..-1]]
else
src = Dir[File.join(cext_dir, config_src)]
end

config_cflags = config['cflags'] || ''
config_cflags = `echo #{config_cflags}`.strip
config_cflags = config_cflags.split(' ')

out = File.expand_path(config['out'], cext_dir)

lls = []

src.each do |src|
ll = File.join(File.dirname(out), File.basename(src, '.*') + '.ll')

clang_args = ["-I#{SULONG_DIR}/include", '-Ilib/ruby/truffle/cext', '-S', '-emit-llvm', *clang_opts, src, '-o', ll]
clang_args = ["-I#{SULONG_DIR}/include", '-Ilib/ruby/truffle/cext', '-S', '-emit-llvm', *config_cflags, *clang_opts, src, '-o', ll]
opt_args = ['-S', '-mem2reg', ll, '-o', ll]

if ENV['USE_SYSTEM_CLANG']
@@ -661,7 +673,7 @@ def test_cexts(*args)
dir = "#{JRUBY_DIR}/test/truffle/cexts/#{gem_name}"
cextc dir
name = File.basename(dir)
run '--graal', '-I', "#{dir}/lib", "#{dir}/bin/#{name}", :out => output_file
run '--graal', "-I#{dir}/lib", "#{dir}/bin/#{name}", :out => output_file
unless File.read(output_file) == File.read("#{dir}/expected.txt")
abort "c extension #{dir} didn't work as expected"
end
@@ -672,15 +684,17 @@ def test_cexts(*args)

[
['oily_png', ['chunky_png-1.3.6', 'oily_png-1.2.0'], ['oily_png']],
['psd_native', ['chunky_png-1.3.6', 'oily_png-1.2.0', 'bindata-2.3.1', 'hashie-3.4.4', 'psd-enginedata-1.1.1', 'psd-2.1.2', 'psd_native-1.1.3'], ['oily_png', 'psd_native']]
].each do |gem_name, dependencies, libs|
['psd_native', ['chunky_png-1.3.6', 'oily_png-1.2.0', 'bindata-2.3.1', 'hashie-3.4.4', 'psd-enginedata-1.1.1', 'psd-2.1.2', 'psd_native-1.1.3'], ['oily_png', 'psd_native']],
['nokogiri', [], ['nokogiri']]
].each do |gem_name, dependencies, libs|
next if gem_name == 'nokogiri' # nokogiri totally excluded
config = "#{JRUBY_DIR}/test/truffle/cexts/#{gem_name}"
cextc config, '-Werror=implicit-function-declaration'
arguments = []
run '--graal',
*(dependencies.map { |d| ['-I', "#{ENV['GEM_HOME']}/gems/#{d}/lib"] }.flatten),
*(libs.map { |l| ['-I', "#{JRUBY_DIR}/test/truffle/cexts/#{l}/lib"] }.flatten),
"#{JRUBY_DIR}/test/truffle/cexts/#{gem_name}/test.rb" unless gem_name == 'psd_native' # psd_native is excluded
*dependencies.map { |d| "-I#{ENV['GEM_HOME']}/gems/#{d}/lib" },
*libs.map { |l| "-I#{JRUBY_DIR}/test/truffle/cexts/#{l}/lib" },
"#{JRUBY_DIR}/test/truffle/cexts/#{gem_name}/test.rb" unless gem_name == 'psd_native' # psd_native is excluded just for compilation
end
end
private :test_cexts
@@ -1027,8 +1041,8 @@ def benchmark(*args)
run_args = []
run_args.push '--graal' unless args.delete('--no-graal') || args.include?('list')
run_args.push '-J-G:+TruffleCompilationExceptionsAreFatal'
run_args.push '-I', "#{Utilities.find_gem('deep-bench')}/lib" rescue nil
run_args.push '-I', "#{Utilities.find_gem('benchmark-ips')}/lib" rescue nil
run_args.push "-I#{Utilities.find_gem('deep-bench')}/lib" rescue nil
run_args.push "-I#{Utilities.find_gem('benchmark-ips')}/lib" rescue nil
run_args.push "#{Utilities.find_gem('benchmark-interface')}/bin/benchmark"
run_args.push *args
run *run_args
1 change: 1 addition & 0 deletions truffle/src/main/c/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
openssl is from MRI 2.3.1
2 changes: 2 additions & 0 deletions truffle/src/main/c/openssl/.jruby-cext-build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
src: ./*.c
out: ../../../../../lib/ruby/truffle/openssl/openssl.su
1,122 changes: 1,122 additions & 0 deletions truffle/src/main/c/openssl/depend

Large diffs are not rendered by default.

26 changes: 26 additions & 0 deletions truffle/src/main/c/openssl/deprecation.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# frozen_string_literal: false
module OpenSSL
def self.deprecated_warning_flag
unless flag = (@deprecated_warning_flag ||= nil)
if try_compile("", flag = "-Werror=deprecated-declarations")
if with_config("broken-apple-openssl")
flag = "-Wno-deprecated-declarations"
end
$warnflags << " #{flag}"
else
flag = ""
end
@deprecated_warning_flag = flag
end
flag
end

def self.check_func(func, header)
have_func(func, header, deprecated_warning_flag)
end

def self.check_func_or_macro(func, header)
check_func(func, header) or
have_macro(func, header) && $defs.push("-DHAVE_#{func.upcase}")
end
end
Empty file.
157 changes: 157 additions & 0 deletions truffle/src/main/c/openssl/extconf.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
# -*- coding: us-ascii -*-
# frozen_string_literal: false
=begin
= Info
'OpenSSL for Ruby 2' project
Copyright (C) 2002 Michal Rokos <m.rokos@sh.cvut.cz>
All rights reserved.
= Licence
This program is licensed under the same licence as Ruby.
(See the file 'LICENCE'.)
=end

require "mkmf"
require File.expand_path('../deprecation', __FILE__)

dir_config("openssl")
dir_config("kerberos")

Logging::message "=== OpenSSL for Ruby configurator ===\n"

# Add -Werror=deprecated-declarations to $warnflags if available
OpenSSL.deprecated_warning_flag

##
# Adds -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")
end

Logging::message "=== Checking for system dependent stuff... ===\n"
have_library("nsl", "t_open")
have_library("socket", "socket")
have_header("assert.h")

Logging::message "=== Checking for required stuff... ===\n"
if $mingw
have_library("wsock32")
have_library("gdi32")
end

result = pkg_config("openssl") && have_header("openssl/ssl.h")
unless result
result = have_header("openssl/ssl.h")
result &&= %w[crypto libeay32].any? {|lib| have_library(lib, "CRYPTO_malloc")}
result &&= %w[ssl ssleay32].any? {|lib| have_library(lib, "SSL_new")}
unless result
Logging::message "=== Checking for required stuff failed. ===\n"
Logging::message "Makefile wasn't created. Fix the errors above.\n"
exit 1
end
end

result = checking_for("OpenSSL version is 0.9.8 or later") {
try_static_assert("OPENSSL_VERSION_NUMBER >= 0x00908000L", "openssl/opensslv.h")
}
unless result
raise "OpenSSL 0.9.8 or later required."
end

unless OpenSSL.check_func("SSL_library_init()", "openssl/ssl.h")
raise "Ignore OpenSSL broken by Apple.\nPlease use another openssl. (e.g. using `configure --with-openssl-dir=/path/to/openssl')"
end

Logging::message "=== Checking for OpenSSL features... ===\n"
# compile options

# check OPENSSL_NO_{SSL2,SSL3_METHOD} macro: on some environment, these symbols
# exist even if compiled with no-ssl2 or no-ssl3-method.
unless have_macro("OPENSSL_NO_SSL2", "openssl/opensslconf.h")
have_func("SSLv2_method")
end
unless have_macro("OPENSSL_NO_SSL3_METHOD", "openssl/opensslconf.h")
have_func("SSLv3_method")
end
have_func("TLSv1_1_method")
have_func("TLSv1_2_method")
have_func("RAND_egd")
engines = %w{builtin_engines openbsd_dev_crypto dynamic 4758cca aep atalla chil
cswift nuron sureware ubsec padlock capi gmp gost cryptodev aesni}
engines.each { |name|
OpenSSL.check_func_or_macro("ENGINE_load_#{name}", "openssl/engine.h")
}

# added in 0.9.8X
have_func("EVP_CIPHER_CTX_new")
have_func("EVP_CIPHER_CTX_free")

# added in 1.0.0
have_func("ASN1_TIME_adj")
have_func("EVP_CIPHER_CTX_copy")
have_func("EVP_PKEY_base_id")
have_func("HMAC_CTX_copy")
have_func("PKCS5_PBKDF2_HMAC")
have_func("X509_NAME_hash_old")
have_func("X509_STORE_CTX_get0_current_crl")
have_func("X509_STORE_set_verify_cb")
have_func("i2d_ASN1_SET_ANY")
have_func("SSL_SESSION_cmp") # removed
OpenSSL.check_func_or_macro("SSL_set_tlsext_host_name", "openssl/ssl.h")
have_struct_member("CRYPTO_THREADID", "ptr", "openssl/crypto.h")

# added in 1.0.1
have_func("SSL_CTX_set_next_proto_select_cb")
have_macro("EVP_CTRL_GCM_GET_TAG", ['openssl/evp.h']) && $defs.push("-DHAVE_AUTHENTICATED_ENCRYPTION")

# added in 1.0.2
have_func("EC_curve_nist2nid")
have_func("X509_REVOKED_dup")
have_func("X509_STORE_CTX_get0_store")
have_func("SSL_CTX_set_alpn_select_cb")
OpenSSL.check_func_or_macro("SSL_CTX_set1_curves_list", "openssl/ssl.h")
OpenSSL.check_func_or_macro("SSL_CTX_set_ecdh_auto", "openssl/ssl.h")
OpenSSL.check_func_or_macro("SSL_get_server_tmp_key", "openssl/ssl.h")
have_func("SSL_is_server")

# added in 1.1.0
have_func("CRYPTO_lock") || $defs.push("-DHAVE_OPENSSL_110_THREADING_API")
have_struct_member("SSL", "ctx", "openssl/ssl.h") || $defs.push("-DHAVE_OPAQUE_OPENSSL")
have_func("BN_GENCB_new")
have_func("BN_GENCB_free")
have_func("BN_GENCB_get_arg")
have_func("EVP_MD_CTX_new")
have_func("EVP_MD_CTX_free")
have_func("HMAC_CTX_new")
have_func("HMAC_CTX_free")
OpenSSL.check_func("RAND_pseudo_bytes", "openssl/rand.h") # deprecated
have_func("X509_STORE_get_ex_data")
have_func("X509_STORE_set_ex_data")
have_func("X509_CRL_get0_signature")
have_func("X509_REQ_get0_signature")
have_func("X509_REVOKED_get0_serialNumber")
have_func("X509_REVOKED_get0_revocationDate")
have_func("X509_get0_tbs_sigalg")
have_func("X509_STORE_CTX_get0_untrusted")
have_func("X509_STORE_CTX_get0_cert")
have_func("X509_STORE_CTX_get0_chain")
have_func("OCSP_SINGLERESP_get0_id")
have_func("SSL_CTX_get_ciphers")
have_func("X509_up_ref")
have_func("X509_CRL_up_ref")
have_func("X509_STORE_up_ref")
have_func("SSL_SESSION_up_ref")
have_func("EVP_PKEY_up_ref")
OpenSSL.check_func_or_macro("SSL_CTX_set_tmp_ecdh_callback", "openssl/ssl.h") # removed
OpenSSL.check_func_or_macro("SSL_CTX_set_min_proto_version", "openssl/ssl.h")
have_func("SSL_CTX_get_security_level")

Logging::message "=== Checking done. ===\n"

create_header
create_makefile("openssl") {|conf|
conf << "THREAD_MODEL = #{CONFIG["THREAD_MODEL"]}\n"
}
Logging::message "Done.\n"
171 changes: 171 additions & 0 deletions truffle/src/main/c/openssl/openssl_missing.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
/*
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
*/
/*
* This program is licensed under the same licence as Ruby.
* (See the file 'LICENCE'.)
*/
#include RUBY_EXTCONF_H

#include <string.h> /* memcpy() */
#if !defined(OPENSSL_NO_ENGINE)
# include <openssl/engine.h>
#endif
#if !defined(OPENSSL_NO_HMAC)
# include <openssl/hmac.h>
#endif
#include <openssl/x509_vfy.h>

#include "openssl_missing.h"

/* added in 0.9.8X */
#if !defined(HAVE_EVP_CIPHER_CTX_NEW)
EVP_CIPHER_CTX *
EVP_CIPHER_CTX_new(void)
{
EVP_CIPHER_CTX *ctx = OPENSSL_malloc(sizeof(EVP_CIPHER_CTX));
if (!ctx)
return NULL;
EVP_CIPHER_CTX_init(ctx);
return ctx;
}
#endif

#if !defined(HAVE_EVP_CIPHER_CTX_FREE)
void
EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *ctx)
{
if (ctx) {
EVP_CIPHER_CTX_cleanup(ctx);
OPENSSL_free(ctx);
}
}
#endif

/* added in 1.0.0 */
#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, const EVP_CIPHER_CTX *in)
{
memcpy(out, in, sizeof(EVP_CIPHER_CTX));

#if !defined(OPENSSL_NO_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(OPENSSL_NO_HMAC)
#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));

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 1;
}
#endif /* HAVE_HMAC_CTX_COPY */
#endif /* NO_HMAC */

/* added in 1.0.2 */
#if !defined(OPENSSL_NO_EC)
#if !defined(HAVE_EC_CURVE_NIST2NID)
static struct {
const char *name;
int nid;
} nist_curves[] = {
{"B-163", NID_sect163r2},
{"B-233", NID_sect233r1},
{"B-283", NID_sect283r1},
{"B-409", NID_sect409r1},
{"B-571", NID_sect571r1},
{"K-163", NID_sect163k1},
{"K-233", NID_sect233k1},
{"K-283", NID_sect283k1},
{"K-409", NID_sect409k1},
{"K-571", NID_sect571k1},
{"P-192", NID_X9_62_prime192v1},
{"P-224", NID_secp224r1},
{"P-256", NID_X9_62_prime256v1},
{"P-384", NID_secp384r1},
{"P-521", NID_secp521r1}
};

int
EC_curve_nist2nid(const char *name)
{
size_t i;
for (i = 0; i < (sizeof(nist_curves) / sizeof(nist_curves[0])); i++) {
if (!strcmp(nist_curves[i].name, name))
return nist_curves[i].nid;
}
return NID_undef;
}
#endif
#endif

/*** added in 1.1.0 ***/
#if !defined(HAVE_HMAC_CTX_NEW)
HMAC_CTX *
HMAC_CTX_new(void)
{
HMAC_CTX *ctx = OPENSSL_malloc(sizeof(HMAC_CTX));
if (!ctx)
return NULL;
HMAC_CTX_init(ctx);
return ctx;
}
#endif

#if !defined(HAVE_HMAC_CTX_FREE)
void
HMAC_CTX_free(HMAC_CTX *ctx)
{
if (ctx) {
HMAC_CTX_cleanup(ctx);
OPENSSL_free(ctx);
}
}
#endif

#if !defined(HAVE_X509_CRL_GET0_SIGNATURE)
void
X509_CRL_get0_signature(ASN1_BIT_STRING **psig, X509_ALGOR **palg, X509_CRL *crl)
{
if (psig != NULL)
*psig = crl->signature;
if (palg != NULL)
*palg = crl->sig_alg;
}
#endif

#if !defined(HAVE_X509_REQ_GET0_SIGNATURE)
void
X509_REQ_get0_signature(ASN1_BIT_STRING **psig, X509_ALGOR **palg, X509_REQ *req)
{
if (psig != NULL)
*psig = req->signature;
if (palg != NULL)
*palg = req->sig_alg;
}
#endif
236 changes: 236 additions & 0 deletions truffle/src/main/c/openssl/openssl_missing.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,236 @@
/*
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
*/
/*
* This program is licensed under the same licence as Ruby.
* (See the file 'LICENCE'.)
*/
#if !defined(_OSSL_OPENSSL_MISSING_H_)
#define _OSSL_OPENSSL_MISSING_H_

#include "ruby/config.h"

/* added in 0.9.8X */
#if !defined(HAVE_EVP_CIPHER_CTX_NEW)
EVP_CIPHER_CTX *EVP_CIPHER_CTX_new(void);
#endif

#if !defined(HAVE_EVP_CIPHER_CTX_FREE)
void EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *ctx);
#endif

/* added in 1.0.0 */
#if !defined(HAVE_EVP_PKEY_BASE_ID)
# define EVP_PKEY_base_id(pkey) EVP_PKEY_type((pkey)->type)
#endif

#if !defined(HAVE_EVP_CIPHER_CTX_COPY)
int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, const EVP_CIPHER_CTX *in);
#endif

#if !defined(HAVE_HMAC_CTX_COPY)
int HMAC_CTX_copy(HMAC_CTX *out, HMAC_CTX *in);
#endif

#if !defined(HAVE_X509_STORE_CTX_GET0_CURRENT_CRL)
# define X509_STORE_CTX_get0_current_crl(x) ((x)->current_crl)
#endif

#if !defined(HAVE_X509_STORE_SET_VERIFY_CB)
# define X509_STORE_set_verify_cb X509_STORE_set_verify_cb_func
#endif

#if !defined(HAVE_I2D_ASN1_SET_ANY)
# define i2d_ASN1_SET_ANY(sk, x) i2d_ASN1_SET_OF_ASN1_TYPE((sk), (x), \
i2d_ASN1_TYPE, V_ASN1_SET, V_ASN1_UNIVERSAL, 0)
#endif

/* added in 1.0.2 */
#if !defined(OPENSSL_NO_EC)
#if !defined(HAVE_EC_CURVE_NIST2NID)
int EC_curve_nist2nid(const char *);
#endif
#endif

#if !defined(HAVE_X509_REVOKED_DUP)
# define X509_REVOKED_dup(rev) (X509_REVOKED *)ASN1_dup((i2d_of_void *)i2d_X509_REVOKED, \
(d2i_of_void *)d2i_X509_REVOKED, (char *)(rev))
#endif

#if !defined(HAVE_X509_STORE_CTX_GET0_STORE)
# define X509_STORE_CTX_get0_store(x) ((x)->ctx)
#endif

#if !defined(HAVE_SSL_IS_SERVER)
# define SSL_is_server(s) ((s)->server)
#endif

/* added in 1.1.0 */
#if !defined(HAVE_BN_GENCB_NEW)
# define BN_GENCB_new() ((BN_GENCB *)OPENSSL_malloc(sizeof(BN_GENCB)))
#endif

#if !defined(HAVE_BN_GENCB_FREE)
# define BN_GENCB_free(cb) OPENSSL_free(cb)
#endif

#if !defined(HAVE_BN_GENCB_GET_ARG)
# define BN_GENCB_get_arg(cb) (cb)->arg
#endif

#if !defined(HAVE_EVP_MD_CTX_NEW)
# define EVP_MD_CTX_new EVP_MD_CTX_create
#endif

#if !defined(HAVE_EVP_MD_CTX_FREE)
# define EVP_MD_CTX_free EVP_MD_CTX_destroy
#endif

#if !defined(HAVE_HMAC_CTX_NEW)
HMAC_CTX *HMAC_CTX_new(void);
#endif

#if !defined(HAVE_HMAC_CTX_FREE)
void HMAC_CTX_free(HMAC_CTX *ctx);
#endif

#if !defined(HAVE_X509_STORE_GET_EX_DATA)
# define X509_STORE_get_ex_data(x, idx) \
CRYPTO_get_ex_data(&(x)->ex_data, (idx))
#endif

#if !defined(HAVE_X509_STORE_SET_EX_DATA)
# define X509_STORE_set_ex_data(x, idx, data) \
CRYPTO_set_ex_data(&(x)->ex_data, (idx), (data))
# define X509_STORE_get_ex_new_index(l, p, newf, dupf, freef) \
CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_X509_STORE, (l), (p), \
(newf), (dupf), (freef))
#endif

#if !defined(HAVE_X509_CRL_GET0_SIGNATURE)
void X509_CRL_get0_signature(ASN1_BIT_STRING **psig, X509_ALGOR **palg, X509_CRL *crl);
#endif

#if !defined(HAVE_X509_REQ_GET0_SIGNATURE)
void X509_REQ_get0_signature(ASN1_BIT_STRING **psig, X509_ALGOR **palg, X509_REQ *req);
#endif

#if !defined(HAVE_X509_REVOKED_GET0_SERIALNUMBER)
# define X509_REVOKED_get0_serialNumber(x) ((x)->serialNumber)
#endif

#if !defined(HAVE_X509_REVOKED_GET0_REVOCATIONDATE)
# define X509_REVOKED_get0_revocationDate(x) ((x)->revocationDate)
#endif

#if !defined(HAVE_X509_GET0_TBS_SIGALG)
# define X509_get0_tbs_sigalg(x) ((x)->cert_info->signature)
#endif

#if !defined(HAVE_X509_STORE_CTX_GET0_UNTRUSTED)
# define X509_STORE_CTX_get0_untrusted(x) ((x)->untrusted)
#endif

#if !defined(HAVE_X509_STORE_CTX_GET0_CERT)
# define X509_STORE_CTX_get0_cert(x) ((x)->cert)
#endif

#if !defined(HAVE_X509_STORE_CTX_GET0_CHAIN)
# define X509_STORE_CTX_get0_chain(ctx) X509_STORE_CTX_get_chain(ctx)
#endif

#if !defined(HAVE_OCSP_SINGLERESP_GET0_ID)
# define OCSP_SINGLERESP_get0_id(s) ((s)->certId)
#endif

#if !defined(HAVE_SSL_CTX_GET_CIPHERS)
# define SSL_CTX_get_ciphers(ctx) ((ctx)->cipher_list)
#endif

#if !defined(HAVE_X509_UP_REF)
# define X509_up_ref(x) \
CRYPTO_add(&(x)->references, 1, CRYPTO_LOCK_X509)
#endif

#if !defined(HAVE_X509_CRL_UP_REF)
# define X509_CRL_up_ref(x) \
CRYPTO_add(&(x)->references, 1, CRYPTO_LOCK_X509_CRL);
#endif

#if !defined(HAVE_X509_STORE_UP_REF)
# define X509_STORE_up_ref(x) \
CRYPTO_add(&(x)->references, 1, CRYPTO_LOCK_X509_STORE);
#endif

#if !defined(HAVE_SSL_SESSION_UP_REF)
# define SSL_SESSION_up_ref(x) \
CRYPTO_add(&(x)->references, 1, CRYPTO_LOCK_SSL_SESSION);
#endif

#if !defined(HAVE_EVP_PKEY_UP_REF)
# define EVP_PKEY_up_ref(x) \
CRYPTO_add(&(x)->references, 1, CRYPTO_LOCK_EVP_PKEY);
#endif

#if !defined(HAVE_OPAQUE_OPENSSL)
#define IMPL_PKEY_GETTER(_type, _name) \
static inline _type *EVP_PKEY_get0_##_type(EVP_PKEY *pkey) { \
return pkey->pkey._name; }
#define IMPL_KEY_ACCESSOR2(_type, _group, a1, a2, _fail_cond) \
static inline void _type##_get0_##_group(_type *obj, const BIGNUM **a1, const BIGNUM **a2) { \
if (a1) *a1 = obj->a1; \
if (a2) *a2 = obj->a2; } \
static inline int _type##_set0_##_group(_type *obj, BIGNUM *a1, BIGNUM *a2) { \
if (_fail_cond) return 0; \
BN_clear_free(obj->a1); obj->a1 = a1; \
BN_clear_free(obj->a2); obj->a2 = a2; \
return 1; }
#define IMPL_KEY_ACCESSOR3(_type, _group, a1, a2, a3, _fail_cond) \
static inline void _type##_get0_##_group(_type *obj, const BIGNUM **a1, const BIGNUM **a2, const BIGNUM **a3) { \
if (a1) *a1 = obj->a1; \
if (a2) *a2 = obj->a2; \
if (a3) *a3 = obj->a3; } \
static inline int _type##_set0_##_group(_type *obj, BIGNUM *a1, BIGNUM *a2, BIGNUM *a3) { \
if (_fail_cond) return 0; \
BN_clear_free(obj->a1); obj->a1 = a1; \
BN_clear_free(obj->a2); obj->a2 = a2; \
BN_clear_free(obj->a3); obj->a3 = a3; \
return 1; }

#if !defined(OPENSSL_NO_RSA)
IMPL_PKEY_GETTER(RSA, rsa)
IMPL_KEY_ACCESSOR3(RSA, key, n, e, d, (n == obj->n || e == obj->e || (obj->d && d == obj->d)))
IMPL_KEY_ACCESSOR2(RSA, factors, p, q, (p == obj->p || q == obj->q))
IMPL_KEY_ACCESSOR3(RSA, crt_params, dmp1, dmq1, iqmp, (dmp1 == obj->dmp1 || dmq1 == obj->dmq1 || iqmp == obj->iqmp))
#endif

#if !defined(OPENSSL_NO_DSA)
IMPL_PKEY_GETTER(DSA, dsa)
IMPL_KEY_ACCESSOR2(DSA, key, pub_key, priv_key, (pub_key == obj->pub_key || (obj->priv_key && priv_key == obj->priv_key)))
IMPL_KEY_ACCESSOR3(DSA, pqg, p, q, g, (p == obj->p || q == obj->q || g == obj->g))
#endif

#if !defined(OPENSSL_NO_DH)
IMPL_PKEY_GETTER(DH, dh)
IMPL_KEY_ACCESSOR2(DH, key, pub_key, priv_key, (pub_key == obj->pub_key || (obj->priv_key && priv_key == obj->priv_key)))
IMPL_KEY_ACCESSOR3(DH, pqg, p, q, g, (p == obj->p || obj->q && q == obj->q || g == obj->g))
static inline ENGINE *DH_get0_engine(DH *dh) { return dh->engine; }
#endif

#if !defined(OPENSSL_NO_EC)
IMPL_PKEY_GETTER(EC_KEY, ec)
#endif

#undef IMPL_PKEY_GETTER
#undef IMPL_KEY_ACCESSOR2
#undef IMPL_KEY_ACCESSOR3
#endif /* HAVE_OPAQUE_OPENSSL */

#if defined(HAVE_AUTHENTICATED_ENCRYPTION) && !defined(EVP_CTRL_AEAD_GET_TAG)
# define EVP_CTRL_AEAD_GET_TAG EVP_CTRL_GCM_GET_TAG
# define EVP_CTRL_AEAD_SET_TAG EVP_CTRL_GCM_SET_TAG
#endif

#endif /* _OSSL_OPENSSL_MISSING_H_ */
1,234 changes: 1,234 additions & 0 deletions truffle/src/main/c/openssl/ossl.c

Large diffs are not rendered by default.

229 changes: 229 additions & 0 deletions truffle/src/main/c/openssl/ossl.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
/*
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
*/
/*
* This program is licensed under the same licence as Ruby.
* (See the file 'LICENCE'.)
*/
#if !defined(_OSSL_H_)
#define _OSSL_H_

#include RUBY_EXTCONF_H

#if 0
mOSSL = rb_define_module("OpenSSL");
mX509 = rb_define_module_under(mOSSL, "X509");
#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 <ruby/io.h>
#include <ruby/thread.h>

#include <openssl/opensslv.h>

#ifdef HAVE_ASSERT_H
# include <assert.h>
#else
# define assert(condition)
#endif

#if defined(_WIN32) && !defined(LIBRESSL_VERSION_NUMBER)
# include <openssl/e_os2.h>
# if !defined(OPENSSL_SYS_WIN32)
# define OPENSSL_SYS_WIN32 1
# endif
# include <winsock2.h>
#endif
#include <errno.h>
#include <openssl/err.h>
#include <openssl/asn1.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>
#if !defined(_WIN32)
# include <openssl/crypto.h>
#endif
#if !defined(OPENSSL_NO_ENGINE)
# include <openssl/engine.h>
#endif
#if !defined(OPENSSL_NO_OCSP)
# include <openssl/ocsp.h>
#endif

/*
* 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 (%"PRIsVALUE")! (Expected kind of %"PRIsVALUE")",\
rb_obj_class(obj), (klass));\
}\
} while (0)

#define OSSL_Check_Instance(obj, klass) do {\
if (!rb_obj_is_instance_of((obj), (klass))) {\
ossl_raise(rb_eTypeError, "wrong argument (%"PRIsVALUE")! (Expected instance of %"PRIsVALUE")",\
rb_obj_class(obj), (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(const unsigned 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_x509name_sk2ary(STACK_OF(X509_NAME) *names);
VALUE ossl_buf2str(char *buf, int len);
#define ossl_str_adjust(str, p) \
do{\
long len = RSTRING_LEN(str);\
long newlen = (long)((p) - (unsigned char*)RSTRING_PTR(str));\
assert(newlen <= len);\
rb_str_set_len((str), newlen);\
}while(0)

/*
* Our default PEM callback
*/
/* Convert the argument to String and validate the length. Note this may raise. */
VALUE ossl_pem_passwd_value(VALUE);
/* Can be casted to pem_password_cb. If a password (String) is passed as the
* "arbitrary data" (typically the last parameter of PEM_{read,write}_
* functions), uses the value. If not, but a block is given, yields to it.
* If not either, fallbacks to PEM_def_callback() which reads from stdin. */
int ossl_pem_passwd_cb(char *, int, int, void *);

/*
* Clear BIO* with this in PEM/DER fallback scenarios to avoid decoding
* errors piling up in OpenSSL::Errors
*/
#define OSSL_BIO_reset(bio) do { \
(void)BIO_reset((bio)); \
ossl_clear_error(); \
} while (0)

/*
* ERRor messages
*/
#define OSSL_ErrMsg() ERR_reason_error_string(ERR_get_error())
NORETURN(void ossl_raise(VALUE, const char *, ...));
VALUE ossl_exc_new(VALUE, const char *, ...);
/* Clear OpenSSL error queue. If dOSSL is set, rb_warn() them. */
void ossl_clear_error(void);

/*
* Verify callback
*/
extern int ossl_store_ctx_ex_verify_cb_idx;
extern int ossl_store_ex_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(...) do { \
if (dOSSL == Qtrue) { \
fprintf(stderr, "OSSL_DEBUG: "); \
fprintf(stderr, __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);

#endif /* _OSSL_H_ */
1,994 changes: 1,994 additions & 0 deletions truffle/src/main/c/openssl/ossl_asn1.c

Large diffs are not rendered by default.

66 changes: 66 additions & 0 deletions truffle/src/main/c/openssl/ossl_asn1.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* 'OpenSSL for Ruby' team members
* Copyright (C) 2003
* All rights reserved.
*/
/*
* This program is licensed 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 *);
#if defined(HAVE_ASN1_TIME_ADJ)
/* Splits VALUE to seconds and offset days. VALUE is typically a Time or an
* Integer. This is used when updating ASN1_*TIME with ASN1_TIME_adj() or
* X509_time_adj_ex(). We can't use ASN1_TIME_set() and X509_time_adj() because
* they have the Year 2038 issue on sizeof(time_t) == 4 environment */
void ossl_time_split(VALUE, time_t *, int *);
#else
time_t time_to_time_t(VALUE);
#endif

/*
* 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
87 changes: 87 additions & 0 deletions truffle/src/main/c/openssl/ossl_bio.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/*
* 'OpenSSL for Ruby' team members
* Copyright (C) 2003
* All rights reserved.
*/
/*
* This program is licensed 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 (RB_TYPE_P(obj, T_FILE)) {
rb_io_t *fptr;
FILE *fp;
int fd;

GetOpenFile(obj, fptr);
rb_io_check_readable(fptr);
if ((fd = rb_cloexec_dup(FPTR_TO_FD(fptr))) < 0){
rb_sys_fail(0);
}
rb_update_max_fd(fd);
if (!(fp = fdopen(fd, "r"))){
int e = errno;
close(fd);
rb_syserr_fail(e, 0);
}
if (!(bio = BIO_new_fp(fp, BIO_CLOSE))){
fclose(fp);
ossl_raise(eOSSLError, NULL);
}
}
else {
StringValue(obj);
bio = BIO_new_mem_buf(RSTRING_PTR(obj), RSTRING_LENINT(obj));
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;
}
19 changes: 19 additions & 0 deletions truffle/src/main/c/openssl/ossl_bio.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* 'OpenSSL for Ruby' team members
* Copyright (C) 2003
* All rights reserved.
*/
/*
* This program is licensed 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
1,116 changes: 1,116 additions & 0 deletions truffle/src/main/c/openssl/ossl_bn.c

Large diffs are not rendered by default.

23 changes: 23 additions & 0 deletions truffle/src/main/c/openssl/ossl_bn.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
*/
/*
* This program is licensed 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;

extern BN_CTX *ossl_bn_ctx;

VALUE ossl_bn_new(const BIGNUM *);
BIGNUM *GetBNPtr(VALUE);
void Init_ossl_bn(void);


#endif /* _OSS_BN_H_ */
958 changes: 958 additions & 0 deletions truffle/src/main/c/openssl/ossl_cipher.c

Large diffs are not rendered by default.

20 changes: 20 additions & 0 deletions truffle/src/main/c/openssl/ossl_cipher.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
*/
/*
* This program is licensed under the same licence as Ruby.
* (See the file 'LICENCE'.)
*/
#if !defined(_OSSL_CIPHER_H_)
#define _OSSL_CIPHER_H_

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_ */
82 changes: 82 additions & 0 deletions truffle/src/main/c/openssl/ossl_config.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
*/
/*
* This program is licensed under the same licence as Ruby.
* (See the file 'LICENCE'.)
*/
#include "ossl.h"


/*
* Classes
*/
VALUE cConfig;
/* Document-class: OpenSSL::ConfigError
*
* General error for openssl library configuration files. Including formatting,
* parsing errors, etc.
*/
VALUE eConfigError;

/*
* Public
*/

/*
* GetConfigPtr is a public C-level function for getting OpenSSL CONF struct
* from an OpenSSL::Config(eConfig) instance. We decided to implement
* OpenSSL::Config in Ruby level but we need to pass native CONF struct for
* some OpenSSL features such as X509V3_EXT_*.
*/
CONF *
GetConfigPtr(VALUE obj)
{
CONF *conf;
VALUE str;
BIO *bio;
long eline = -1;

OSSL_Check_Kind(obj, cConfig);
str = rb_funcall(obj, rb_intern("to_s"), 0);
bio = ossl_obj2bio(str);
conf = NCONF_new(NULL);
if(!conf){
BIO_free(bio);
ossl_raise(eConfigError, NULL);
}
if(!NCONF_load_bio(conf, bio, &eline)){
BIO_free(bio);
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;
}

/* Document-const: DEFAULT_CONFIG_FILE
*
* The default system configuration file for openssl
*/

/*
* INIT
*/
void
Init_ossl_config(void)
{
char *default_config_file;
eConfigError = rb_define_class_under(mOSSL, "ConfigError", eOSSLError);
cConfig = rb_define_class_under(mOSSL, "Config", rb_cObject);

default_config_file = CONF_get1_default_config_file();
rb_define_const(cConfig, "DEFAULT_CONFIG_FILE",
rb_str_new2(default_config_file));
OPENSSL_free(default_config_file);
/* methods are defined by openssl/config.rb */
}
20 changes: 20 additions & 0 deletions truffle/src/main/c/openssl/ossl_config.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
*/
/*
* This program is licensed 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_ */
449 changes: 449 additions & 0 deletions truffle/src/main/c/openssl/ossl_digest.c

Large diffs are not rendered by default.

20 changes: 20 additions & 0 deletions truffle/src/main/c/openssl/ossl_digest.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
*/
/*
* This program is licensed under the same licence as Ruby.
* (See the file 'LICENCE'.)
*/
#if !defined(_OSSL_DIGEST_H_)
#define _OSSL_DIGEST_H_

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_ */
576 changes: 576 additions & 0 deletions truffle/src/main/c/openssl/ossl_engine.c

Large diffs are not rendered by default.

19 changes: 19 additions & 0 deletions truffle/src/main/c/openssl/ossl_engine.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* '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 licensed 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 */
382 changes: 382 additions & 0 deletions truffle/src/main/c/openssl/ossl_hmac.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,382 @@
/*
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
*/
/*
* This program is licensed under the same licence as Ruby.
* (See the file 'LICENCE'.)
*/
#if !defined(OPENSSL_NO_HMAC)

#include "ossl.h"

#define NewHMAC(klass) \
TypedData_Wrap_Struct((klass), &ossl_hmac_type, 0)
#define GetHMAC(obj, ctx) do { \
TypedData_Get_Struct((obj), HMAC_CTX, &ossl_hmac_type, (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(void *ctx)
{
HMAC_CTX_free(ctx);
}

static const rb_data_type_t ossl_hmac_type = {
"OpenSSL/HMAC",
{
0, ossl_hmac_free,
},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
};

static VALUE
ossl_hmac_alloc(VALUE klass)
{
VALUE obj;
HMAC_CTX *ctx;

obj = NewHMAC(klass);
ctx = HMAC_CTX_new();
if (!ctx)
ossl_raise(eHMACError, NULL);
RTYPEDDATA_DATA(obj) = ctx;

return obj;
}


/*
* call-seq:
* HMAC.new(key, digest) -> hmac
*
* Returns an instance of OpenSSL::HMAC set with the key and digest
* algorithm to be used. The instance represents the initial state of
* the message authentication code before any data has been processed.
* To process data with it, use the instance method #update with your
* data as an argument.
*
* === Example
*
* key = 'key'
* digest = OpenSSL::Digest.new('sha1')
* instance = OpenSSL::HMAC.new(key, digest)
* #=> f42bb0eeb018ebbd4597ae7213711ec60760843f
* instance.class
* #=> OpenSSL::HMAC
*
* === A note about comparisons
*
* Two instances won't be equal when they're compared, even if they have the
* same value. Use #to_s or #hexdigest to return the authentication code that
* the instance represents. For example:
*
* other_instance = OpenSSL::HMAC.new('key', OpenSSL::Digest.new('sha1'))
* #=> f42bb0eeb018ebbd4597ae7213711ec60760843f
* instance
* #=> f42bb0eeb018ebbd4597ae7213711ec60760843f
* instance == other_instance
* #=> false
* instance.to_s == other_instance.to_s
* #=> true
*
*/
static VALUE
ossl_hmac_initialize(VALUE self, VALUE key, VALUE digest)
{
HMAC_CTX *ctx;

StringValue(key);
GetHMAC(self, ctx);
HMAC_Init_ex(ctx, RSTRING_PTR(key), RSTRING_LENINT(key),
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, "HMAC_CTX_copy");
return self;
}

/*
* call-seq:
* hmac.update(string) -> self
*
* Returns +self+ updated with the message to be authenticated.
* Can be called repeatedly with chunks of the message.
*
* === Example
*
* first_chunk = 'The quick brown fox jumps '
* second_chunk = 'over the lazy dog'
*
* instance.update(first_chunk)
* #=> 5b9a8038a65d571076d97fe783989e52278a492a
* instance.update(second_chunk)
* #=> de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9
*
*/
static VALUE
ossl_hmac_update(VALUE self, VALUE data)
{
HMAC_CTX *ctx;

StringValue(data);
GetHMAC(self, ctx);
HMAC_Update(ctx, (unsigned char *)RSTRING_PTR(data), RSTRING_LEN(data));

return self;
}

static void
hmac_final(HMAC_CTX *ctx, unsigned char **buf, unsigned int *buf_len)
{
HMAC_CTX *final;

final = HMAC_CTX_new();
if (!final)
ossl_raise(eHMACError, "HMAC_CTX_new");

if (!HMAC_CTX_copy(final, ctx)) {
HMAC_CTX_free(final);
ossl_raise(eHMACError, "HMAC_CTX_copy");
}

if (!(*buf = OPENSSL_malloc(HMAC_size(final)))) {
HMAC_CTX_free(final);
OSSL_Debug("Allocating %d mem", (int)HMAC_size(final));
ossl_raise(eHMACError, "Cannot allocate memory for hmac");
}
HMAC_Final(final, *buf, buf_len);
HMAC_CTX_free(final);
}

/*
* call-seq:
* hmac.digest -> string
*
* Returns the authentication code an instance represents as a binary string.
*
* === Example
*
* instance = OpenSSL::HMAC.new('key', OpenSSL::Digest.new('sha1'))
* #=> f42bb0eeb018ebbd4597ae7213711ec60760843f
* instance.digest
* #=> "\xF4+\xB0\xEE\xB0\x18\xEB\xBDE\x97\xAEr\x13q\x1E\xC6\a`\x84?"
*
*/
static VALUE
ossl_hmac_digest(VALUE self)
{
HMAC_CTX *ctx;
unsigned char *buf;
unsigned int buf_len;
VALUE digest;

GetHMAC(self, ctx);
hmac_final(ctx, &buf, &buf_len);
digest = ossl_buf2str((char *)buf, buf_len);

return digest;
}

/*
* call-seq:
* hmac.hexdigest -> string
*
* Returns the authentication code an instance represents as a hex-encoded
* string.
*
*/
static VALUE
ossl_hmac_hexdigest(VALUE self)
{
HMAC_CTX *ctx;
unsigned char *buf;
char *hexbuf;
unsigned int buf_len;
VALUE hexdigest;

GetHMAC(self, ctx);
hmac_final(ctx, &buf, &buf_len);
if (string2hex(buf, buf_len, &hexbuf, NULL) != 2 * (int)buf_len) {
OPENSSL_free(buf);
ossl_raise(eHMACError, "Memory alloc error");
}
OPENSSL_free(buf);
hexdigest = ossl_buf2str(hexbuf, 2 * buf_len);

return hexdigest;
}

/*
* call-seq:
* hmac.reset -> self
*
* Returns +self+ as it was when it was first initialized, with all processed
* data cleared from it.
*
* === Example
*
* data = "The quick brown fox jumps over the lazy dog"
* instance = OpenSSL::HMAC.new('key', OpenSSL::Digest.new('sha1'))
* #=> f42bb0eeb018ebbd4597ae7213711ec60760843f
*
* instance.update(data)
* #=> de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9
* instance.reset
* #=> f42bb0eeb018ebbd4597ae7213711ec60760843f
*
*/
static VALUE
ossl_hmac_reset(VALUE self)
{
HMAC_CTX *ctx;

GetHMAC(self, ctx);
HMAC_Init_ex(ctx, NULL, 0, NULL, NULL);

return self;
}

/*
* call-seq:
* HMAC.digest(digest, key, data) -> aString
*
* Returns the authentication code as a binary string. The +digest+ parameter
* must be an instance of OpenSSL::Digest.
*
* === Example
*
* key = 'key'
* data = 'The quick brown fox jumps over the lazy dog'
* digest = OpenSSL::Digest.new('sha1')
*
* hmac = OpenSSL::HMAC.digest(digest, key, data)
* #=> "\xDE|\x9B\x85\xB8\xB7\x8A\xA6\xBC\x8Az6\xF7\n\x90p\x1C\x9D\xB4\xD9"
*
*/
static VALUE
ossl_hmac_s_digest(VALUE klass, VALUE digest, VALUE key, VALUE data)
{
unsigned char *buf;
unsigned int buf_len;

StringValue(key);
StringValue(data);
buf = HMAC(GetDigestPtr(digest), RSTRING_PTR(key), RSTRING_LENINT(key),
(unsigned char *)RSTRING_PTR(data), RSTRING_LEN(data), NULL, &buf_len);

return rb_str_new((const char *)buf, buf_len);
}

/*
* call-seq:
* HMAC.hexdigest(digest, key, data) -> aString
*
* Returns the authentication code as a hex-encoded string. The +digest+
* parameter must be an instance of OpenSSL::Digest.
*
* === Example
*
* key = 'key'
* data = 'The quick brown fox jumps over the lazy dog'
* digest = OpenSSL::Digest.new('sha1')
*
* hmac = OpenSSL::HMAC.hexdigest(digest, key, data)
* #=> "de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9"
*
*/
static VALUE
ossl_hmac_s_hexdigest(VALUE klass, VALUE digest, VALUE key, VALUE data)
{
unsigned char *buf;
char *hexbuf;
unsigned int buf_len;
VALUE hexdigest;

StringValue(key);
StringValue(data);

buf = HMAC(GetDigestPtr(digest), RSTRING_PTR(key), RSTRING_LENINT(key),
(unsigned char *)RSTRING_PTR(data), RSTRING_LEN(data), NULL, &buf_len);
if (string2hex(buf, buf_len, &hexbuf, NULL) != 2 * (int)buf_len) {
ossl_raise(eHMACError, "Cannot convert buf to hexbuf");
}
hexdigest = ossl_buf2str(hexbuf, 2 * buf_len);

return hexdigest;
}

/*
* INIT
*/
void
Init_ossl_hmac(void)
{
#if 0
/* :nodoc: */
mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */
#endif

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, "reset", ossl_hmac_reset, 0);
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(void)
{
rb_warning("HMAC is not available: OpenSSL is compiled without HMAC.");
}
#endif /* NO_HMAC */
18 changes: 18 additions & 0 deletions truffle/src/main/c/openssl/ossl_hmac.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
*/
/*
* This program is licensed 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_ */
405 changes: 405 additions & 0 deletions truffle/src/main/c/openssl/ossl_ns_spki.c

Large diffs are not rendered by default.

19 changes: 19 additions & 0 deletions truffle/src/main/c/openssl/ossl_ns_spki.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
*/
/*
* This program is licensed 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_ */
1,955 changes: 1,955 additions & 0 deletions truffle/src/main/c/openssl/ossl_ocsp.c

Large diffs are not rendered by default.

23 changes: 23 additions & 0 deletions truffle/src/main/c/openssl/ossl_ocsp.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* '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 licensed under the same licence as Ruby.
* (See the file 'LICENCE'.)
*/
#if !defined(_OSSL_OCSP_H_)
#define _OSSL_OCSP_H_

#if !defined(OPENSSL_NO_OCSP)
extern VALUE mOCSP;
extern VALUE cOPCSReq;
extern VALUE cOPCSRes;
extern VALUE cOPCSBasicRes;
#endif

void Init_ossl_ocsp(void);

#endif /* _OSSL_OCSP_H_ */
234 changes: 234 additions & 0 deletions truffle/src/main/c/openssl/ossl_pkcs12.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
/*
* This program is licensed under the same licence as Ruby.
* (See the file 'LICENCE'.)
*/
#include "ossl.h"

#define NewPKCS12(klass) \
TypedData_Wrap_Struct((klass), &ossl_pkcs12_type, 0)

#define SetPKCS12(obj, p12) do { \
if(!(p12)) ossl_raise(rb_eRuntimeError, "PKCS12 wasn't initialized."); \
RTYPEDDATA_DATA(obj) = (p12); \
} while (0)

#define GetPKCS12(obj, p12) do { \
TypedData_Get_Struct((obj), PKCS12, &ossl_pkcs12_type, (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 cPKCS12;
VALUE ePKCS12Error;

/*
* Private
*/
static void
ossl_pkcs12_free(void *ptr)
{
PKCS12_free(ptr);
}

static const rb_data_type_t ossl_pkcs12_type = {
"OpenSSL/PKCS12",
{
0, ossl_pkcs12_free,
},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
};

static VALUE
ossl_pkcs12_s_allocate(VALUE klass)
{
PKCS12 *p12;
VALUE obj;

obj = NewPKCS12(klass);
if(!(p12 = PKCS12_new())) ossl_raise(ePKCS12Error, NULL);
SetPKCS12(obj, p12);

return obj;
}

/*
* call-seq:
* PKCS12.create(pass, name, key, cert [, ca, [, key_pbe [, cert_pbe [, key_iter [, mac_iter [, keytype]]]]]])
*
* === Parameters
* * +pass+ - string
* * +name+ - A string describing the key.
* * +key+ - Any PKey.
* * +cert+ - A X509::Certificate.
* * * The public_key portion of the certificate must contain a valid public key.
* * * The not_before and not_after fields must be filled in.
* * +ca+ - An optional array of X509::Certificate's.
* * +key_pbe+ - string
* * +cert_pbe+ - string
* * +key_iter+ - integer
* * +mac_iter+ - integer
* * +keytype+ - An integer representing an MSIE specific extension.
*
* Any optional arguments may be supplied as nil to preserve the OpenSSL defaults.
*
* See the OpenSSL documentation for PKCS12_create().
*/
static VALUE
ossl_pkcs12_s_create(int argc, VALUE *argv, VALUE self)
{
VALUE pass, name, pkey, cert, ca, key_nid, cert_nid, key_iter, mac_iter, keytype;
VALUE obj;
char *passphrase, *friendlyname;
EVP_PKEY *key;
X509 *x509;
STACK_OF(X509) *x509s;
int nkey = 0, ncert = 0, kiter = 0, miter = 0, ktype = 0;
PKCS12 *p12;

rb_scan_args(argc, argv, "46", &pass, &name, &pkey, &cert, &ca, &key_nid, &cert_nid, &key_iter, &mac_iter, &keytype);
passphrase = NIL_P(pass) ? NULL : StringValueCStr(pass);
friendlyname = NIL_P(name) ? NULL : StringValueCStr(name);
key = GetPKeyPtr(pkey);
x509 = GetX509CertPtr(cert);
x509s = NIL_P(ca) ? NULL : ossl_x509_ary2sk(ca);
/* TODO: make a VALUE to nid function */
if (!NIL_P(key_nid)) {
if ((nkey = OBJ_txt2nid(StringValueCStr(key_nid))) == NID_undef)
ossl_raise(rb_eArgError, "Unknown PBE algorithm %"PRIsVALUE, key_nid);
}
if (!NIL_P(cert_nid)) {
if ((ncert = OBJ_txt2nid(StringValueCStr(cert_nid))) == NID_undef)
ossl_raise(rb_eArgError, "Unknown PBE algorithm %"PRIsVALUE, cert_nid);
}
if (!NIL_P(key_iter))
kiter = NUM2INT(key_iter);
if (!NIL_P(mac_iter))
miter = NUM2INT(mac_iter);
if (!NIL_P(keytype))
ktype = NUM2INT(keytype);

obj = NewPKCS12(cPKCS12);
p12 = PKCS12_create(passphrase, friendlyname, key, x509, x509s,
nkey, ncert, kiter, miter, ktype);
sk_X509_pop_free(x509s, X509_free);
if(!p12) ossl_raise(ePKCS12Error, NULL);
SetPKCS12(obj, p12);

ossl_pkcs12_set_key(obj, pkey);
ossl_pkcs12_set_cert(obj, cert);
ossl_pkcs12_set_ca_certs(obj, ca);

return obj;
}

/*
* call-seq:
* PKCS12.new -> pkcs12
* PKCS12.new(str) -> pkcs12
* PKCS12.new(str, pass) -> pkcs12
*
* === Parameters
* * +str+ - Must be a DER encoded PKCS12 string.
* * +pass+ - string
*/
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;
PKCS12 *pkcs = DATA_PTR(self);

if(rb_scan_args(argc, argv, "02", &arg, &pass) == 0) return self;
passphrase = NIL_P(pass) ? NULL : StringValueCStr(pass);
in = ossl_obj2bio(arg);
d2i_PKCS12_bio(in, &pkcs);
DATA_PTR(self) = pkcs;
BIO_free(in);

pkey = cert = ca = Qnil;
/* OpenSSL's bug; PKCS12_parse() puts errors even if it succeeds.
* Fixed in OpenSSL 1.0.0t, 1.0.1p, 1.0.2d */
ERR_set_mark();
if(!PKCS12_parse(pkcs, passphrase, &key, &x509, &x509s))
ossl_raise(ePKCS12Error, "PKCS12_parse");
ERR_pop_to_mark();
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 = (unsigned char *)RSTRING_PTR(str);
if(i2d_PKCS12(p12, &p) <= 0)
ossl_raise(ePKCS12Error, NULL);
ossl_str_adjust(str, p);

return str;
}

void
Init_ossl_pkcs12(void)
{
/*
* Defines a file format commonly used to store private keys with
* accompanying public key certificates, protected with a password-based
* symmetric key.
*/
cPKCS12 = rb_define_class_under(mOSSL, "PKCS12", rb_cObject);
ePKCS12Error = rb_define_class_under(cPKCS12, "PKCS12Error", eOSSLError);
rb_define_singleton_method(cPKCS12, "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);
}
13 changes: 13 additions & 0 deletions truffle/src/main/c/openssl/ossl_pkcs12.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/*
* This program is licensed under the same licence as Ruby.
* (See the file 'LICENCE'.)
*/
#if !defined(_OSSL_PKCS12_H_)
#define _OSSL_PKCS12_H_

extern VALUE cPKCS12;
extern VALUE ePKCS12Error;

void Init_ossl_pkcs12(void);

#endif /* _OSSL_PKCS12_H_ */
184 changes: 184 additions & 0 deletions truffle/src/main/c/openssl/ossl_pkcs5.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
/*
* Copyright (C) 2007 Technorama Ltd. <oss-ruby@technorama.net>
*/
#include "ossl.h"

VALUE mPKCS5;
VALUE ePKCS5;

#ifdef HAVE_PKCS5_PBKDF2_HMAC
/*
* call-seq:
* PKCS5.pbkdf2_hmac(pass, salt, iter, keylen, digest) => string
*
* === Parameters
* * +pass+ - string
* * +salt+ - string - should be at least 8 bytes long.
* * +iter+ - integer - should be greater than 1000. 20000 is better.
* * +keylen+ - integer
* * +digest+ - a string or OpenSSL::Digest object.
*
* Available in OpenSSL 0.9.4.
*
* Digests other than SHA1 may not be supported by other cryptography libraries.
*/
static VALUE
ossl_pkcs5_pbkdf2_hmac(VALUE self, VALUE pass, VALUE salt, VALUE iter, VALUE keylen, VALUE digest)
{
VALUE str;
const EVP_MD *md;
int len = NUM2INT(keylen);

StringValue(pass);
StringValue(salt);
md = GetDigestPtr(digest);

str = rb_str_new(0, len);

if (PKCS5_PBKDF2_HMAC(RSTRING_PTR(pass), RSTRING_LENINT(pass),
(unsigned char *)RSTRING_PTR(salt), RSTRING_LENINT(salt),
NUM2INT(iter), md, len,
(unsigned char *)RSTRING_PTR(str)) != 1)
ossl_raise(ePKCS5, "PKCS5_PBKDF2_HMAC");

return str;
}
#else
#define ossl_pkcs5_pbkdf2_hmac rb_f_notimplement
#endif


/*
* call-seq:
* PKCS5.pbkdf2_hmac_sha1(pass, salt, iter, keylen) => string
*
* === Parameters
* * +pass+ - string
* * +salt+ - string - should be at least 8 bytes long.
* * +iter+ - integer - should be greater than 1000. 20000 is better.
* * +keylen+ - integer
*
* This method is available in almost any version of OpenSSL.
*
* Conforms to rfc2898.
*/
static VALUE
ossl_pkcs5_pbkdf2_hmac_sha1(VALUE self, VALUE pass, VALUE salt, VALUE iter, VALUE keylen)
{
VALUE str;
int len = NUM2INT(keylen);

StringValue(pass);
StringValue(salt);

str = rb_str_new(0, len);

if (PKCS5_PBKDF2_HMAC_SHA1(RSTRING_PTR(pass), RSTRING_LENINT(pass),
(const unsigned char *)RSTRING_PTR(salt), RSTRING_LENINT(salt), NUM2INT(iter),
len, (unsigned char *)RSTRING_PTR(str)) != 1)
ossl_raise(ePKCS5, "PKCS5_PBKDF2_HMAC_SHA1");

return str;
}

void
Init_ossl_pkcs5(void)
{
/*
* Password-based Encryption
*
*/

#if 0
mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */
#endif

/* Document-class: OpenSSL::PKCS5
*
* Provides password-based encryption functionality based on PKCS#5.
* Typically used for securely deriving arbitrary length symmetric keys
* to be used with an OpenSSL::Cipher from passwords. Another use case
* is for storing passwords: Due to the ability to tweak the effort of
* computation by increasing the iteration count, computation can be
* slowed down artificially in order to render possible attacks infeasible.
*
* PKCS5 offers support for PBKDF2 with an OpenSSL::Digest::SHA1-based
* HMAC, or an arbitrary Digest if the underlying version of OpenSSL
* already supports it (>= 0.9.4).
*
* === Parameters
* ==== Password
* Typically an arbitrary String that represents the password to be used
* for deriving a key.
* ==== Salt
* Prevents attacks based on dictionaries of common passwords. It is a
* public value that can be safely stored along with the password (e.g.
* if PBKDF2 is used for password storage). For maximum security, a fresh,
* random salt should be generated for each stored password. According
* to PKCS#5, a salt should be at least 8 bytes long.
* ==== Iteration Count
* Allows to tweak the length that the actual computation will take. The
* larger the iteration count, the longer it will take.
* ==== Key Length
* Specifies the length in bytes of the output that will be generated.
* Typically, the key length should be larger than or equal to the output
* length of the underlying digest function, otherwise an attacker could
* simply try to brute-force the key. According to PKCS#5, security is
* limited by the output length of the underlying digest function, i.e.
* security is not improved if a key length strictly larger than the
* digest output length is chosen. Therefore, when using PKCS5 for
* password storage, it suffices to store values equal to the digest
* output length, nothing is gained by storing larger values.
*
* == Examples
* === Generating a 128 bit key for a Cipher (e.g. AES)
* pass = "secret"
* salt = OpenSSL::Random.random_bytes(16)
* iter = 20000
* key_len = 16
* key = OpenSSL::PKCS5.pbkdf2_hmac_sha1(pass, salt, iter, key_len)
*
* === Storing Passwords
* pass = "secret"
* salt = OpenSSL::Random.random_bytes(16) #store this with the generated value
* iter = 20000
* digest = OpenSSL::Digest::SHA256.new
* len = digest.digest_length
* #the final value to be stored
* value = OpenSSL::PKCS5.pbkdf2_hmac(pass, salt, iter, len, digest)
*
* === Important Note on Checking Passwords
* When comparing passwords provided by the user with previously stored
* values, a common mistake made is comparing the two values using "==".
* Typically, "==" short-circuits on evaluation, and is therefore
* vulnerable to timing attacks. The proper way is to use a method that
* always takes the same amount of time when comparing two values, thus
* not leaking any information to potential attackers. To compare two
* values, the following could be used:
* def eql_time_cmp(a, b)
* unless a.length == b.length
* return false
* end
* cmp = b.bytes.to_a
* result = 0
* a.bytes.each_with_index {|c,i|
* result |= c ^ cmp[i]
* }
* result == 0
* end
* Please note that the premature return in case of differing lengths
* typically does not leak valuable information - when using PKCS#5, the
* length of the values to be compared is of fixed size.
*/

mPKCS5 = rb_define_module_under(mOSSL, "PKCS5");
/* Document-class: OpenSSL::PKCS5::PKCS5Error
*
* Generic Exception class that is raised if an error occurs during a
* computation.
*/
ePKCS5 = rb_define_class_under(mPKCS5, "PKCS5Error", eOSSLError);

rb_define_module_function(mPKCS5, "pbkdf2_hmac", ossl_pkcs5_pbkdf2_hmac, 5);
rb_define_module_function(mPKCS5, "pbkdf2_hmac_sha1", ossl_pkcs5_pbkdf2_hmac_sha1, 4);
}
6 changes: 6 additions & 0 deletions truffle/src/main/c/openssl/ossl_pkcs5.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#if !defined(_OSSL_PKCS5_H_)
#define _OSSL_PKCS5_H_

void Init_ossl_pkcs5(void);

#endif /* _OSSL_PKCS5_H_ */
Loading

0 comments on commit c2ac786

Please sign in to comment.