提交 c9dc0164 编写于 作者: R rhe

import Ruby/OpenSSL 2.0.0.beta.1

* NEWS, {ext,test,sample}/openssl: Import Ruby/OpenSSL 2.0.0.beta.1.
  ext/openssl is now converted into a default gem. The full commit
  history since r55538 can be found at:
  https://github.com/ruby/openssl/compare/08e1881f5663...v2.0.0.beta.1
  [Feature #9612]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@56027 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
上级 28bf4d54
......@@ -123,6 +123,12 @@ with all sufficient information, see the ChangeLog file or Redmine
* Add an into option. [Feature #11191]
* OpenSSL
* OpenSSL is extracted as a gem and the upstream has been migrated to
https://github.com/ruby/openssl. OpenSSL still remains as a default gem.
Refer to its History.md for the full release note. [Feature #9612]
=== Compatibility issues (excluding feature bug fixes)
* Array#sum and Enumerable#sum are implemented. [Feature #12217]
......
......@@ -147,6 +147,7 @@
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")
have_func("X509_get0_notBefore")
Logging::message "=== Checking done. ===\n"
......
......@@ -18,7 +18,7 @@ class Cipher
klass = Class.new(Cipher){
define_method(:initialize){|*args|
cipher_name = args.inject(name){|n, arg| "#{n}-#{arg}" }
super(cipher_name)
super(cipher_name.downcase)
}
}
const_set(name, klass)
......@@ -26,34 +26,42 @@ class Cipher
%w(128 192 256).each{|keylen|
klass = Class.new(Cipher){
define_method(:initialize){|mode|
mode ||= "CBC"
cipher_name = "AES-#{keylen}-#{mode}"
super(cipher_name)
define_method(:initialize){|mode = "CBC"|
super("aes-#{keylen}-#{mode}".downcase)
}
}
const_set("AES#{keylen}", klass)
}
# Generate, set, and return a random key.
# You must call cipher.encrypt or cipher.decrypt before calling this method.
# call-seq:
# cipher.random_key -> key
#
# Generate a random key with OpenSSL::Random.random_bytes and sets it to
# the cipher, and returns it.
#
# You must call #encrypt or #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.
# call-seq:
# cipher.random_iv -> iv
#
# Generate a random IV with OpenSSL::Random.random_bytes and sets it to the
# cipher, and returns it.
#
# You must call #encrypt or #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
# Deprecated.
#
# This class is only provided for backwards compatibility.
# Use OpenSSL::Cipher.
class Cipher < Cipher; end
deprecate_constant :Cipher
end # Cipher
end # OpenSSL
......@@ -53,15 +53,9 @@ def self.digest(name, data)
# 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
# Use OpenSSL::Digest instead.
class Digest < Digest; end # :nodoc:
deprecate_constant :Digest
end # Digest
......
......@@ -4,6 +4,7 @@ module PKey
if defined?(OpenSSL::PKey::DH)
class DH
# :nodoc:
DEFAULT_1024 = new <<-_end_of_pem_
-----BEGIN DH PARAMETERS-----
MIGHAoGBAJ0lOVy0VIr/JebWn0zDwY2h+rqITFOpdNr6ugsgvkDXuucdcChhYExJ
......@@ -12,6 +13,7 @@ class DH
-----END DH PARAMETERS-----
_end_of_pem_
# :nodoc:
DEFAULT_2048 = new <<-_end_of_pem_
-----BEGIN DH PARAMETERS-----
MIIBCAKCAQEA7E6kBrYiyvmKAMzQ7i8WvwVk9Y/+f8S7sCTN712KkK3cqd1jhJDY
......@@ -24,6 +26,7 @@ class DH
_end_of_pem_
end
# :nodoc:
DEFAULT_TMP_DH_CALLBACK = lambda { |ctx, is_export, keylen|
warn "using default DH parameters." if $VERBOSE
case keylen
......
......@@ -16,44 +16,11 @@
module OpenSSL
module SSL
class SSLContext
# :nodoc:
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(":"),
:verify_hostname => true,
:options => -> {
opts = OpenSSL::SSL::OP_ALL
opts &= ~OpenSSL::SSL::OP_DONT_INSERT_EMPTY_FRAGMENTS
......@@ -63,10 +30,50 @@ class SSLContext
}.call
}
if !(OpenSSL::OPENSSL_VERSION.start_with?("OpenSSL") &&
OpenSSL::OPENSSL_VERSION_NUMBER >= 0x10100000)
DEFAULT_PARAMS.merge!(
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
}.join(":"),
)
end
# :nodoc:
DEFAULT_CERT_STORE = OpenSSL::X509::Store.new
DEFAULT_CERT_STORE.set_default_paths
DEFAULT_CERT_STORE.flags = OpenSSL::X509::V_FLAG_CRL_CHECK_ALL
# :nodoc:
INIT_VARS = ["cert", "key", "client_ca", "ca_file", "ca_path",
"timeout", "verify_mode", "verify_depth", "renegotiation_cb",
"verify_callback", "cert_store", "extra_chain_cert",
......@@ -74,7 +81,7 @@ class SSLContext
"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}" }
"npn_select_cb", "verify_hostname"].map { |x| "@#{x}" }
# A callback invoked when DH parameters are required.
#
......@@ -110,13 +117,17 @@ def initialize(version = nil)
end
##
# Sets the parameters for this SSL context to the values in +params+.
# call-seq:
# ctx.set_params(params = {}) -> params
#
# Sets saner defaults optimized for the use with HTTP-like protocols.
#
# If a Hash +params+ is given, the parameters are overridden with it.
# 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) }
......@@ -251,10 +262,17 @@ class SSLSocket
attr_reader :hostname
end
attr_reader :io, :context
attr_accessor :sync_close
# The underlying IO object.
attr_reader :io
alias :to_io :io
# The SSLContext object used in this connection.
attr_reader :context
# Whether to close the underlying socket as well, when the SSL/TLS
# connection is shut down. This defaults to +false+.
attr_accessor :sync_close
# call-seq:
# ssl.sysclose => nil
#
......@@ -268,8 +286,10 @@ def sysclose
io.close if sync_close
end
##
# Perform hostname verification after an SSL connection is established
# call-seq:
# ssl.post_connection_check(hostname) -> true
#
# Perform hostname verification following RFC 6125.
#
# This method MUST be called after calling #connect to ensure that the
# hostname of a remote peer has been verified.
......@@ -277,7 +297,8 @@ 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."
msg += " Anonymous cipher suite #{cipher[0]} was negotiated. " \
"Anonymous suites must be disabled to use peer verification."
end
raise SSLError, msg
end
......@@ -288,6 +309,11 @@ def post_connection_check(hostname)
return true
end
# call-seq:
# ssl.session -> aSession
#
# Returns the SSLSession object currently used, or nil if the session is
# not established.
def session
SSL::Session.new(self)
rescue SSL::Session::SessionError
......
# -*- encoding: utf-8 -*-
# stub: openssl 2.0.0.beta.1 ruby lib
# stub: ext/openssl/extconf.rb
Gem::Specification.new do |s|
s.name = "openssl".freeze
s.version = "2.0.0.beta.1"
s.required_rubygems_version = Gem::Requirement.new("> 1.3.1".freeze) if s.respond_to? :required_rubygems_version=
s.require_paths = ["lib".freeze]
s.authors = ["Martin Bosslet".freeze, "SHIBATA Hiroshi".freeze, "Zachary Scott".freeze, "Kazuki Yamaguchi".freeze]
s.date = "2016-08-29"
s.description = "It wraps the OpenSSL library.".freeze
s.email = ["ruby-core@ruby-lang.org".freeze]
s.extensions = ["ext/openssl/extconf.rb".freeze]
s.extra_rdoc_files = ["CONTRIBUTING.md".freeze, "History.md".freeze, "README.md".freeze]
s.files = ["BSDL".freeze, "CONTRIBUTING.md".freeze, "History.md".freeze, "LICENSE.txt".freeze, "README.md".freeze, "ext/openssl/deprecation.rb".freeze, "ext/openssl/extconf.rb".freeze, "ext/openssl/openssl_missing.c".freeze, "ext/openssl/openssl_missing.h".freeze, "ext/openssl/ossl.c".freeze, "ext/openssl/ossl.h".freeze, "ext/openssl/ossl_asn1.c".freeze, "ext/openssl/ossl_asn1.h".freeze, "ext/openssl/ossl_bio.c".freeze, "ext/openssl/ossl_bio.h".freeze, "ext/openssl/ossl_bn.c".freeze, "ext/openssl/ossl_bn.h".freeze, "ext/openssl/ossl_cipher.c".freeze, "ext/openssl/ossl_cipher.h".freeze, "ext/openssl/ossl_config.c".freeze, "ext/openssl/ossl_config.h".freeze, "ext/openssl/ossl_digest.c".freeze, "ext/openssl/ossl_digest.h".freeze, "ext/openssl/ossl_engine.c".freeze, "ext/openssl/ossl_engine.h".freeze, "ext/openssl/ossl_hmac.c".freeze, "ext/openssl/ossl_hmac.h".freeze, "ext/openssl/ossl_ns_spki.c".freeze, "ext/openssl/ossl_ns_spki.h".freeze, "ext/openssl/ossl_ocsp.c".freeze, "ext/openssl/ossl_ocsp.h".freeze, "ext/openssl/ossl_pkcs12.c".freeze, "ext/openssl/ossl_pkcs12.h".freeze, "ext/openssl/ossl_pkcs5.c".freeze, "ext/openssl/ossl_pkcs5.h".freeze, "ext/openssl/ossl_pkcs7.c".freeze, "ext/openssl/ossl_pkcs7.h".freeze, "ext/openssl/ossl_pkey.c".freeze, "ext/openssl/ossl_pkey.h".freeze, "ext/openssl/ossl_pkey_dh.c".freeze, "ext/openssl/ossl_pkey_dsa.c".freeze, "ext/openssl/ossl_pkey_ec.c".freeze, "ext/openssl/ossl_pkey_rsa.c".freeze, "ext/openssl/ossl_rand.c".freeze, "ext/openssl/ossl_rand.h".freeze, "ext/openssl/ossl_ssl.c".freeze, "ext/openssl/ossl_ssl.h".freeze, "ext/openssl/ossl_ssl_session.c".freeze, "ext/openssl/ossl_version.h".freeze, "ext/openssl/ossl_x509.c".freeze, "ext/openssl/ossl_x509.h".freeze, "ext/openssl/ossl_x509attr.c".freeze, "ext/openssl/ossl_x509cert.c".freeze, "ext/openssl/ossl_x509crl.c".freeze, "ext/openssl/ossl_x509ext.c".freeze, "ext/openssl/ossl_x509name.c".freeze, "ext/openssl/ossl_x509req.c".freeze, "ext/openssl/ossl_x509revoked.c".freeze, "ext/openssl/ossl_x509store.c".freeze, "ext/openssl/ruby_missing.h".freeze, "lib/openssl.rb".freeze, "lib/openssl/bn.rb".freeze, "lib/openssl/buffering.rb".freeze, "lib/openssl/cipher.rb".freeze, "lib/openssl/config.rb".freeze, "lib/openssl/digest.rb".freeze, "lib/openssl/pkey.rb".freeze, "lib/openssl/ssl.rb".freeze, "lib/openssl/x509.rb".freeze]
s.homepage = "https://www.ruby-lang.org/".freeze
s.licenses = ["Ruby".freeze]
s.rdoc_options = ["--main".freeze, "README.md".freeze]
s.required_ruby_version = Gem::Requirement.new(">= 2.3.0".freeze)
s.rubygems_version = "2.6.6".freeze
s.summary = "OpenSSL provides SSL, TLS and general purpose cryptography.".freeze
if s.respond_to? :specification_version then
s.specification_version = 4
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
s.add_development_dependency(%q<rake>.freeze, ["~> 10.3"])
s.add_development_dependency(%q<rake-compiler>.freeze, ["~> 0.9"])
s.add_development_dependency(%q<test-unit>.freeze, ["~> 3.0"])
s.add_development_dependency(%q<rdoc>.freeze, ["~> 4.2"])
else
s.add_dependency(%q<rake>.freeze, ["~> 10.3"])
s.add_dependency(%q<rake-compiler>.freeze, ["~> 0.9"])
s.add_dependency(%q<test-unit>.freeze, ["~> 3.0"])
s.add_dependency(%q<rdoc>.freeze, ["~> 4.2"])
end
else
s.add_dependency(%q<rake>.freeze, ["~> 10.3"])
s.add_dependency(%q<rake-compiler>.freeze, ["~> 0.9"])
s.add_dependency(%q<test-unit>.freeze, ["~> 3.0"])
s.add_dependency(%q<rdoc>.freeze, ["~> 4.2"])
end
end
......@@ -150,7 +150,8 @@ HMAC_CTX_free(HMAC_CTX *ctx)
#if !defined(HAVE_X509_CRL_GET0_SIGNATURE)
void
X509_CRL_get0_signature(ASN1_BIT_STRING **psig, X509_ALGOR **palg, X509_CRL *crl)
X509_CRL_get0_signature(const X509_CRL *crl, const ASN1_BIT_STRING **psig,
const X509_ALGOR **palg)
{
if (psig != NULL)
*psig = crl->signature;
......@@ -161,7 +162,8 @@ X509_CRL_get0_signature(ASN1_BIT_STRING **psig, X509_ALGOR **palg, X509_CRL *crl
#if !defined(HAVE_X509_REQ_GET0_SIGNATURE)
void
X509_REQ_get0_signature(ASN1_BIT_STRING **psig, X509_ALGOR **palg, X509_REQ *req)
X509_REQ_get0_signature(const X509_REQ *req, const ASN1_BIT_STRING **psig,
const X509_ALGOR **palg)
{
if (psig != NULL)
*psig = req->signature;
......
......@@ -110,11 +110,11 @@ void HMAC_CTX_free(HMAC_CTX *ctx);
#endif
#if !defined(HAVE_X509_CRL_GET0_SIGNATURE)
void X509_CRL_get0_signature(ASN1_BIT_STRING **psig, X509_ALGOR **palg, X509_CRL *crl);
void X509_CRL_get0_signature(const X509_CRL *, const ASN1_BIT_STRING **, const X509_ALGOR **);
#endif
#if !defined(HAVE_X509_REQ_GET0_SIGNATURE)
void X509_REQ_get0_signature(ASN1_BIT_STRING **psig, X509_ALGOR **palg, X509_REQ *req);
void X509_REQ_get0_signature(const X509_REQ *, const ASN1_BIT_STRING **, const X509_ALGOR **);
#endif
#if !defined(HAVE_X509_REVOKED_GET0_SERIALNUMBER)
......@@ -231,6 +231,14 @@ IMPL_PKEY_GETTER(EC_KEY, ec)
#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
# define EVP_CTRL_AEAD_SET_IVLEN EVP_CTRL_GCM_SET_IVLEN
#endif
#if !defined(HAVE_X509_GET0_NOTBEFORE)
# define X509_get0_notBefore(x) X509_get_notBefore(x)
# define X509_get0_notAfter(x) X509_get_notAfter(x)
# define X509_CRL_get0_lastUpdate(x) X509_CRL_get_lastUpdate(x)
# define X509_CRL_get0_nextUpdate(x) X509_CRL_get_nextUpdate(x)
#endif
#endif /* _OSSL_OPENSSL_MISSING_H_ */
......@@ -9,40 +9,7 @@
*/
#include "ossl.h"
#include <stdarg.h> /* for ossl_raise */
/*
* String to HEXString conversion
*/
int
string2hex(const unsigned char *buf, int buf_len, char **hexbuf, int *hexbuf_len)
{
static const char hex[]="0123456789abcdef";
int i, len;
if (buf_len < 0 || buf_len > INT_MAX / 2) { /* PARANOIA? */
return -1;
}
len = 2 * buf_len;
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;
}
#include <ruby/thread_native.h> /* for OpenSSL < 1.1.0 locks */
/*
* Data Conversion
......@@ -77,7 +44,7 @@ STACK_OF(type) * \
ossl_protect_##name##_ary2sk(VALUE ary, int *status) \
{ \
return (STACK_OF(type)*)rb_protect( \
(VALUE(*)_((VALUE)))ossl_##name##_ary2sk0, \
(VALUE (*)(VALUE))ossl_##name##_ary2sk0, \
ary, \
status); \
} \
......@@ -97,7 +64,7 @@ OSSL_IMPL_ARY2SK(x509, X509, cX509Cert, DupX509CertPtr)
#define OSSL_IMPL_SK2ARY(name, type) \
VALUE \
ossl_##name##_sk2ary(STACK_OF(type) *sk) \
ossl_##name##_sk2ary(const STACK_OF(type) *sk) \
{ \
type *t; \
int i, num; \
......@@ -136,7 +103,7 @@ ossl_buf2str(char *buf, int len)
VALUE str;
int status = 0;
str = rb_protect((VALUE(*)_((VALUE)))ossl_str_new, len, &status);
str = rb_protect((VALUE (*)(VALUE))ossl_str_new, len, &status);
if(!NIL_P(str)) memcpy(RSTRING_PTR(str), buf, len);
OPENSSL_free(buf);
if(status) rb_jump_tag(status);
......@@ -144,6 +111,21 @@ ossl_buf2str(char *buf, int len)
return str;
}
void
ossl_bin2hex(unsigned char *in, char *out, size_t inlen)
{
const char *hex = "0123456789abcdef";
size_t i;
assert(inlen <= LONG_MAX / 2);
for (i = 0; i < inlen; i++) {
unsigned char p = in[i];
out[i * 2 + 0] = hex[p >> 4];
out[i * 2 + 1] = hex[p & 0x0f];
}
}
/*
* our default PEM callback
*/
......@@ -242,54 +224,54 @@ ossl_pem_passwd_cb(char *buf, int max_len, int flag, void *pwd_)
int ossl_store_ctx_ex_verify_cb_idx;
int ossl_store_ex_verify_cb_idx;
VALUE
struct ossl_verify_cb_args {
VALUE proc;
VALUE preverify_ok;
VALUE store_ctx;
};
static 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);
args->preverify_ok, args->store_ctx);
}
int
ossl_verify_cb(int ok, X509_STORE_CTX *ctx)
ossl_verify_cb_call(VALUE proc, int ok, X509_STORE_CTX *ctx)
{
VALUE proc, rctx, ret;
VALUE rctx, ret;
struct ossl_verify_cb_args args;
int state = 0;
int state;
proc = (VALUE)X509_STORE_CTX_get_ex_data(ctx, ossl_store_ctx_ex_verify_cb_idx);
if (!proc)
proc = (VALUE)X509_STORE_get_ex_data(X509_STORE_CTX_get0_store(ctx), ossl_store_ex_verify_cb_idx);
if (!proc)
if (NIL_P(proc))
return ok;
if (!NIL_P(proc)) {
ret = Qfalse;
rctx = rb_protect((VALUE(*)(VALUE))ossl_x509stctx_new,
(VALUE)ctx, &state);
ret = Qfalse;
rctx = rb_protect((VALUE(*)(VALUE))ossl_x509stctx_new, (VALUE)ctx, &state);
if (state) {
rb_set_errinfo(Qnil);
rb_warn("StoreContext initialization failure");
}
else {
args.proc = proc;
args.preverify_ok = ok ? Qtrue : Qfalse;
args.store_ctx = rctx;
ret = rb_protect((VALUE(*)(VALUE))ossl_call_verify_cb_proc, (VALUE)&args, &state);
if (state) {
rb_set_errinfo(Qnil);
rb_warn("StoreContext initialization failure");
}
else {
args.proc = proc;
args.preverify_ok = ok ? Qtrue : Qfalse;
args.store_ctx = rctx;
ret = rb_protect((VALUE(*)(VALUE))ossl_call_verify_cb_proc, (VALUE)&args, &state);
if (state) {
rb_set_errinfo(Qnil);
rb_warn("exception in verify_callback is ignored");
}
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;
rb_warn("exception in verify_callback is ignored");
}
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;
......@@ -453,24 +435,14 @@ ossl_debug_get(VALUE self)
* call-seq:
* OpenSSL.debug = boolean -> boolean
*
* Turns on or off CRYPTO_MEM_CHECK.
* Also shows some debugging message on stderr.
* Turns on or off debug mode. With debug mode, all erros added to the OpenSSL
* error queue will be printed to stderr.
*/
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");
}
}
dOSSL = RTEST(val) ? Qtrue : Qfalse;
return val;
}
......@@ -483,9 +455,8 @@ ossl_debug_set(VALUE self, VALUE val)
* so otherwise will result in an error.
*
* === Examples
*
* OpenSSL.fips_mode = true # turn FIPS mode on
* OpenSSL.fips_mode = false # and off again
* OpenSSL.fips_mode = true # turn FIPS mode on
* OpenSSL.fips_mode = false # and off again
*/
static VALUE
ossl_fips_mode_set(VALUE self, VALUE enabled)
......@@ -512,7 +483,6 @@ ossl_fips_mode_set(VALUE self, VALUE enabled)
/**
* Stores locks needed for OpenSSL thread safety
*/
#include "ruby/thread_native.h"
static rb_nativethread_lock_t *ossl_locks;
static void
......@@ -602,20 +572,6 @@ static void Init_ossl_locks(void)
* OpenSSL provides SSL, TLS and general purpose cryptography. It wraps the
* OpenSSL[http://www.openssl.org/] library.
*
* = Install
*
* OpenSSL comes bundled with the Standard Library of Ruby.
*
* This means the OpenSSL extension is compiled with Ruby and packaged on
* build. During compile time, Ruby will need to link against the OpenSSL
* library on your system. However, you cannot use openssl provided by Apple to
* build standard library openssl.
*
* If you use OSX, you should install another openssl and run ```./configure
* --with-openssl-dir=/path/to/another-openssl```. For Homebrew user, run `brew
* install openssl` and then ```./configure --with-openssl-dir=`brew --prefix
* openssl` ```.
*
* = Examples
*
* All examples assume you have loaded OpenSSL with:
......@@ -660,10 +616,12 @@ static void Init_ossl_locks(void)
*
* key2 = OpenSSL::PKey::RSA.new File.read 'private_key.pem'
* key2.public? # => true
* key2.private? # => true
*
* or
*
* key3 = OpenSSL::PKey::RSA.new File.read 'public_key.pem'
* key3.public? # => true
* key3.private? # => false
*
* === Loading an Encrypted Key
......@@ -910,7 +868,7 @@ static void Init_ossl_locks(void)
* ca_key = OpenSSL::PKey::RSA.new 2048
* pass_phrase = 'my secure pass phrase goes here'
*
* cipher = OpenSSL::Cipher::Cipher.new 'AES-128-CBC'
* cipher = OpenSSL::Cipher.new 'AES-128-CBC'
*
* open 'ca_key.pem', 'w', 0400 do |io|
* io.write ca_key.export(cipher, pass_phrase)
......@@ -1063,15 +1021,21 @@ static void Init_ossl_locks(void)
* SSLSocket#connect must be called to initiate the SSL handshake and start
* encryption. A key and certificate are not required for the client socket.
*
* Note that SSLSocket#close doesn't close the underlying socket by default. Set
* SSLSocket#sync_close to true if you want.
*
* require 'socket'
*
* tcp_socket = TCPSocket.new 'localhost', 5000
* ssl_client = OpenSSL::SSL::SSLSocket.new tcp_socket, context
* ssl_client.sync_close = true
* ssl_client.connect
*
* ssl_client.puts "hello server!"
* puts ssl_client.gets
*
* ssl_client.close # shutdown the TLS connection and close tcp_socket
*
* === Peer Verification
*
* An unverified SSL connection does not provide much security. For enhanced
......@@ -1160,11 +1124,14 @@ Init_openssl(void)
/*
* Boolean indicating whether OpenSSL is FIPS-enabled or not
*/
rb_define_const(mOSSL, "OPENSSL_FIPS",
#ifdef OPENSSL_FIPS
rb_define_const(mOSSL, "OPENSSL_FIPS", Qtrue);
Qtrue
#else
rb_define_const(mOSSL, "OPENSSL_FIPS", Qfalse);
Qfalse
#endif
);
rb_define_module_function(mOSSL, "fips_mode=", ossl_fips_mode_set, 1);
/*
......
......@@ -96,20 +96,15 @@ extern VALUE eOSSLError;
}\
} 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_x509_sk2ary(const STACK_OF(X509) *certs);
VALUE ossl_x509crl_sk2ary(const STACK_OF(X509_CRL) *crl);
VALUE ossl_x509name_sk2ary(const STACK_OF(X509_NAME) *names);
VALUE ossl_buf2str(char *buf, int len);
#define ossl_str_adjust(str, p) \
do{\
......@@ -118,6 +113,11 @@ do{\
assert(newlen <= len);\
rb_str_set_len((str), newlen);\
}while(0)
/*
* Convert binary string to hex string. The caller is responsible for
* ensuring out has (2 * len) bytes of capacity.
*/
void ossl_bin2hex(unsigned char *in, char *out, size_t len);
/*
* Our default PEM callback
......@@ -154,14 +154,7 @@ void ossl_clear_error(void);
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 *);
int ossl_verify_cb_call(VALUE, int, X509_STORE_CTX *);
/*
* String to DER String
......
......@@ -28,7 +28,7 @@ static VALUE ossl_asn1eoc_initialize(VALUE self);
* DATE conversion
*/
VALUE
asn1time_to_time(ASN1_TIME *time)
asn1time_to_time(const ASN1_TIME *time)
{
struct tm tm;
VALUE argv[6];
......@@ -103,7 +103,7 @@ time_to_time_t(VALUE time)
* STRING conversion
*/
VALUE
asn1str_to_str(ASN1_STRING *str)
asn1str_to_str(const ASN1_STRING *str)
{
return rb_str_new((const char *)str->data, str->length);
}
......@@ -114,7 +114,7 @@ asn1str_to_str(ASN1_STRING *str)
*/
#define DO_IT_VIA_RUBY 0
VALUE
asn1integer_to_num(ASN1_INTEGER *ai)
asn1integer_to_num(const ASN1_INTEGER *ai)
{
BIGNUM *bn;
#if DO_IT_VIA_RUBY
......@@ -126,7 +126,8 @@ asn1integer_to_num(ASN1_INTEGER *ai)
ossl_raise(rb_eTypeError, "ASN1_INTEGER is NULL!");
}
if (ai->type == V_ASN1_ENUMERATED)
bn = ASN1_ENUMERATED_to_BN(ai, NULL);
/* const_cast: workaround for old OpenSSL */
bn = ASN1_ENUMERATED_to_BN((ASN1_ENUMERATED *)ai, NULL);
else
bn = ASN1_INTEGER_to_BN(ai, NULL);
......@@ -383,7 +384,7 @@ decode_int(unsigned char* der, long length)
p = der;
if(!(ai = d2i_ASN1_INTEGER(NULL, &p, length)))
ossl_raise(eASN1Error, NULL);
ret = rb_protect((VALUE(*)_((VALUE)))asn1integer_to_num,
ret = rb_protect((VALUE (*)(VALUE))asn1integer_to_num,
(VALUE)ai, &status);
ASN1_INTEGER_free(ai);
if(status) rb_jump_tag(status);
......@@ -423,7 +424,7 @@ decode_enum(unsigned char* der, long length)
p = der;
if(!(ai = d2i_ASN1_ENUMERATED(NULL, &p, length)))
ossl_raise(eASN1Error, NULL);
ret = rb_protect((VALUE(*)_((VALUE)))asn1integer_to_num,
ret = rb_protect((VALUE (*)(VALUE))asn1integer_to_num,
(VALUE)ai, &status);
ASN1_ENUMERATED_free(ai);
if(status) rb_jump_tag(status);
......@@ -485,7 +486,7 @@ decode_time(unsigned char* der, long length)
p = der;
if(!(time = d2i_ASN1_TIME(NULL, &p, length)))
ossl_raise(eASN1Error, NULL);
ret = rb_protect((VALUE(*)_((VALUE)))asn1time_to_time,
ret = rb_protect((VALUE (*)(VALUE))asn1time_to_time,
(VALUE)time, &status);
ASN1_TIME_free(time);
if(status) rb_jump_tag(status);
......@@ -1471,7 +1472,8 @@ Init_ossl_asn1(void)
int i;
#if 0
mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */
mOSSL = rb_define_module("OpenSSL");
eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
#endif
sUNIVERSAL = rb_intern("UNIVERSAL");
......@@ -1806,10 +1808,6 @@ Init_ossl_asn1(void)
* it is not typically allocated this way, but rather that are received from
* parsed ASN1 encodings.
*
* While OpenSSL::ASN1::ObjectId.new will allocate a new ObjectId, it is
* not typically allocated this way, but rather that are received from
* parsed ASN1 encodings.
*
* === Additional attributes
* * +sn+: the short name as defined in <openssl/objects.h>.
* * +ln+: the long name as defined in <openssl/objects.h>.
......
......@@ -13,7 +13,7 @@
/*
* ASN1_DATE conversions
*/
VALUE asn1time_to_time(ASN1_TIME *);
VALUE asn1time_to_time(const 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
......@@ -27,12 +27,12 @@ time_t time_to_time_t(VALUE);
/*
* ASN1_STRING conversions
*/
VALUE asn1str_to_str(ASN1_STRING *);
VALUE asn1str_to_str(const ASN1_STRING *);
/*
* ASN1_INTEGER conversions
*/
VALUE asn1integer_to_num(ASN1_INTEGER *);
VALUE asn1integer_to_num(const ASN1_INTEGER *);
ASN1_INTEGER *num_to_asn1integer(VALUE, ASN1_INTEGER *);
/*
......
......@@ -51,7 +51,7 @@ BIO *
ossl_protect_obj2bio(VALUE obj, int *status)
{
BIO *ret = NULL;
ret = (BIO*)rb_protect((VALUE(*)_((VALUE)))ossl_obj2bio, obj, status);
ret = (BIO*)rb_protect((VALUE (*)(VALUE))ossl_obj2bio, obj, status);
return ret;
}
......@@ -70,7 +70,7 @@ ossl_membio2str0(BIO *bio)
VALUE
ossl_protect_membio2str(BIO *bio, int *status)
{
return rb_protect((VALUE(*)_((VALUE)))ossl_membio2str0, (VALUE)bio, status);
return rb_protect((VALUE (*)(VALUE))ossl_membio2str0, (VALUE)bio, status);
}
VALUE
......
......@@ -51,8 +51,6 @@ static const rb_data_type_t ossl_bn_type = {
VALUE cBN;
/* Document-class: OpenSSL::BNError
*
* BNError < OpenSSLError
*
* Generic Error for all of OpenSSL::BN (big num)
*/
......@@ -77,25 +75,66 @@ ossl_bn_new(const BIGNUM *bn)
return obj;
}
static BIGNUM *
integer_to_bnptr(VALUE obj, BIGNUM *orig)
{
BIGNUM *bn;
if (FIXNUM_P(obj)) {
long i;
unsigned char bin[sizeof(long)];
long n = FIX2LONG(obj);
unsigned long un = labs(n);
for (i = sizeof(long) - 1; 0 <= i; i--) {
bin[i] = un & 0xff;
un >>= 8;
}
bn = BN_bin2bn(bin, sizeof(bin), orig);
if (!bn)
ossl_raise(eBNError, "BN_bin2bn");
if (n < 0)
BN_set_negative(bn, 1);
}
else { /* assuming Bignum */
size_t len = rb_absint_size(obj, NULL);
unsigned char *bin;
VALUE buf;
int sign;
if (INT_MAX < len) {
rb_raise(eBNError, "bignum too long");
}
bin = (unsigned char*)ALLOCV_N(unsigned char, buf, len);
sign = rb_integer_pack(obj, bin, len, 1, 0, INTEGER_PACK_BIG_ENDIAN);
bn = BN_bin2bn(bin, (int)len, orig);
ALLOCV_END(buf);
if (!bn)
ossl_raise(eBNError, "BN_bin2bn");
if (sign < 0)
BN_set_negative(bn, 1);
}
return bn;
}
static BIGNUM *
try_convert_to_bnptr(VALUE obj)
{
BIGNUM *bn = NULL;
VALUE newobj;
if (RTEST(rb_obj_is_kind_of(obj, cBN))) {
if (rb_obj_is_kind_of(obj, cBN)) {
GetBN(obj, bn);
} else switch (TYPE(obj)) {
case T_FIXNUM:
case T_BIGNUM:
obj = rb_String(obj);
newobj = NewBN(cBN); /* GC bug */
if (!BN_dec2bn(&bn, StringValueCStr(obj))) {
ossl_raise(eBNError, NULL);
}
SetBN(newobj, bn); /* Handle potencial mem leaks */
break;
}
else if (RB_INTEGER_TYPE_P(obj)) {
newobj = NewBN(cBN); /* Handle potencial mem leaks */
bn = integer_to_bnptr(obj, NULL);
SetBN(newobj, bn);
}
return bn;
}
......@@ -135,6 +174,7 @@ ossl_bn_alloc(VALUE klass)
/* Document-method: OpenSSL::BN.new
*
* call-seq:
* OpenSSL::BN.new => aBN
* OpenSSL::BN.new(bn) => aBN
* OpenSSL::BN.new(integer) => aBN
......@@ -154,45 +194,13 @@ ossl_bn_initialize(int argc, VALUE *argv, VALUE self)
base = NUM2INT(bs);
}
if (RB_TYPE_P(str, T_FIXNUM)) {
long i;
unsigned char bin[sizeof(long)];
long n = FIX2LONG(str);
unsigned long un = labs(n);
for (i = sizeof(long) - 1; 0 <= i; i--) {
bin[i] = un&0xff;
un >>= 8;
}
if (RB_INTEGER_TYPE_P(str)) {
GetBN(self, bn);
if (!BN_bin2bn(bin, sizeof(bin), bn)) {
ossl_raise(eBNError, NULL);
}
if (n < 0) BN_set_negative(bn, 1);
return self;
}
else if (RB_TYPE_P(str, T_BIGNUM)) {
size_t len = rb_absint_size(str, NULL);
unsigned char *bin;
VALUE buf;
int sign;
if (INT_MAX < len) {
rb_raise(eBNError, "bignum too long");
}
bin = (unsigned char*)ALLOCV_N(unsigned char, buf, len);
sign = rb_integer_pack(str, bin, len, 1, 0, INTEGER_PACK_BIG_ENDIAN);
integer_to_bnptr(str, bn);
GetBN(self, bn);
if (!BN_bin2bn(bin, (int)len, bn)) {
ALLOCV_END(buf);
ossl_raise(eBNError, NULL);
}
ALLOCV_END(buf);
if (sign < 0) BN_set_negative(bn, 1);
return self;
}
if (RTEST(rb_obj_is_kind_of(str, cBN))) {
BIGNUM *other;
......@@ -239,11 +247,11 @@ ossl_bn_initialize(int argc, VALUE *argv, VALUE self)
*
* === Parameters
* * +base+ - integer
* * * Valid values:
* * * * 0 - MPI
* * * * 2 - binary
* * * * 10 - the default
* * * * 16 - hex
* Valid values:
* * 0 - MPI
* * 2 - binary
* * 10 - the default
* * 16 - hex
*/
static VALUE
ossl_bn_to_s(int argc, VALUE *argv, VALUE self)
......@@ -346,18 +354,21 @@ ossl_bn_coerce(VALUE self, VALUE other)
/*
* Document-method: OpenSSL::BN#zero?
* call-seq:
* bn.zero? => true | false
*/
BIGNUM_BOOL1(is_zero)
/*
* Document-method: OpenSSL::BN#one?
* call-seq:
* bn.one? => true | false
*/
BIGNUM_BOOL1(is_one)
/*
* Document-method: OpenSSL::BN#odd?
* call-seq:
* bn.odd? => true | false
*/
BIGNUM_BOOL1(is_odd)
......@@ -383,6 +394,7 @@ BIGNUM_BOOL1(is_odd)
/*
* Document-method: OpenSSL::BN#sqr
* call-seq:
* bn.sqr => aBN
*/
BIGNUM_1c(sqr)
......@@ -408,12 +420,14 @@ BIGNUM_1c(sqr)
/*
* Document-method: OpenSSL::BN#+
* call-seq:
* bn + bn2 => aBN
*/
BIGNUM_2(add)
/*
* Document-method: OpenSSL::BN#-
* call-seq:
* bn - bn2 => aBN
*/
BIGNUM_2(sub)
......@@ -439,42 +453,49 @@ BIGNUM_2(sub)
/*
* Document-method: OpenSSL::BN#*
* call-seq:
* bn * bn2 => aBN
*/
BIGNUM_2c(mul)
/*
* Document-method: OpenSSL::BN#%
* call-seq:
* bn % bn2 => aBN
*/
BIGNUM_2c(mod)
/*
* Document-method: OpenSSL::BN#**
* call-seq:
* bn ** bn2 => aBN
*/
BIGNUM_2c(exp)
/*
* Document-method: OpenSSL::BN#gcd
* call-seq:
* bn.gcd(bn2) => aBN
*/
BIGNUM_2c(gcd)
/*
* Document-method: OpenSSL::BN#mod_sqr
* call-seq:
* bn.mod_sqr(bn2) => aBN
*/
BIGNUM_2c(mod_sqr)
/*
* Document-method: OpenSSL::BN#mod_inverse
* call-seq:
* bn.mod_inverse(bn2) => aBN
*/
BIGNUM_2c(mod_inverse)
/*
* Document-method: OpenSSL::BN#/
* call-seq:
* bn1 / bn2 => [result, remainder]
*
* Division of OpenSSL::BN instances
......@@ -529,24 +550,28 @@ ossl_bn_div(VALUE self, VALUE other)
/*
* Document-method: OpenSSL::BN#mod_add
* call-seq:
* bn.mod_add(bn1, bn2) -> aBN
*/
BIGNUM_3c(mod_add)
/*
* Document-method: OpenSSL::BN#mod_sub
* call-seq:
* bn.mod_sub(bn1, bn2) -> aBN
*/
BIGNUM_3c(mod_sub)
/*
* Document-method: OpenSSL::BN#mod_mul
* call-seq:
* bn.mod_mul(bn1, bn2) -> aBN
*/
BIGNUM_3c(mod_mul)
/*
* Document-method: OpenSSL::BN#mod_exp
* call-seq:
* bn.mod_exp(bn1, bn2) -> aBN
*/
BIGNUM_3c(mod_exp)
......@@ -565,29 +590,31 @@ BIGNUM_3c(mod_exp)
/*
* Document-method: OpenSSL::BN#set_bit!
* call-seq:
* bn.set_bit!(bit) -> self
*/
BIGNUM_BIT(set_bit)
/*
* Document-method: OpenSSL::BN#clear_bit!
* call-seq:
* bn.clear_bit!(bit) -> self
*/
BIGNUM_BIT(clear_bit)
/*
* Document-method: OpenSSL::BN#mask_bit!
* call-seq:
* bn.mask_bit!(bit) -> self
*/
BIGNUM_BIT(mask_bits)
/* Document-method: OpenSSL::BN#bit_set?
* call-seq:
* bn.bit_set?(bit) => true | false
*
* Returns boolean of whether +bit+ is set.
* Bitwise operations for openssl BIGNUMs.
*
* bn.bit_set?(bit) => true | false
*
*/
static VALUE
ossl_bn_is_bit_set(VALUE self, VALUE bit)
......@@ -653,12 +680,14 @@ BIGNUM_SHIFT(rshift)
/*
* Document-method: OpenSSL::BN#lshift!
* call-seq:
* bn.lshift!(bits) -> self
*/
BIGNUM_SELF_SHIFT(lshift)
/*
* Document-method: OpenSSL::BN#rshift!
* call-seq:
* bn.rshift!(bits) -> self
*/
BIGNUM_SELF_SHIFT(rshift)
......@@ -722,6 +751,7 @@ BIGNUM_RAND(pseudo_rand)
/*
* Document-method: OpenSSL::BN.rand_range
* call-seq:
* BN.rand_range(range) -> aBN
*
*/
......@@ -729,6 +759,7 @@ BIGNUM_RAND_RANGE(rand)
/*
* Document-method: OpenSSL::BN.pseudo_rand_range
* call-seq:
* BN.pseudo_rand_range(range) -> aBN
*
*/
......@@ -785,17 +816,19 @@ ossl_bn_s_generate_prime(int argc, VALUE *argv, VALUE klass)
{ \
BIGNUM *bn; \
GetBN(self, bn); \
return INT2FIX(BN_##func(bn)); \
return INT2NUM(BN_##func(bn)); \
}
/*
* Document-method: OpenSSL::BN#num_bytes
* call-seq:
* bn.num_bytes => integer
*/
BIGNUM_NUM(num_bytes)
/*
* Document-method: OpenSSL::BN#num_bits
* call-seq:
* bn.num_bits => integer
*/
BIGNUM_NUM(num_bits)
......@@ -824,21 +857,24 @@ ossl_bn_copy(VALUE self, VALUE other)
{ \
BIGNUM *bn1, *bn2 = GetBNPtr(other); \
GetBN(self, bn1); \
return INT2FIX(BN_##func(bn1, bn2)); \
return INT2NUM(BN_##func(bn1, bn2)); \
}
/*
* Document-method: OpenSSL::BN#cmp
* call-seq:
* bn.cmp(bn2) => integer
*/
/*
* Document-method: OpenSSL::BN#<=>
* call-seq:
* bn <=> bn2 => integer
*/
BIGNUM_CMP(cmp)
/*
* Document-method: OpenSSL::BN#ucmp
* call-seq:
* bn.ucmp(bn2) => integer
*/
BIGNUM_CMP(ucmp)
......@@ -921,9 +957,9 @@ ossl_bn_hash(VALUE self)
* bn.prime? => true | false
* bn.prime?(checks) => true | false
*
* Performs a Miller-Rabin probabilistic primality test with +checks+
* iterations. If +nchecks+ is not specified, a number of iterations is used
* that yields a false positive rate of at most 2^-80 for random input.
* Performs a Miller-Rabin probabilistic primality test with +checks+
* iterations. If +nchecks+ is not specified, a number of iterations is used
* that yields a false positive rate of at most 2^-80 for random input.
*
* === Parameters
* * +checks+ - integer
......@@ -957,8 +993,8 @@ ossl_bn_is_prime(int argc, VALUE *argv, VALUE self)
* bn.prime_fasttest?(checks) => true | false
* bn.prime_fasttest?(checks, trial_div) => true | false
*
* Performs a Miller-Rabin primality test. This is same as #prime? except this
* first attempts trial divisions with some small primes.
* Performs a Miller-Rabin primality test. This is same as #prime? except this
* first attempts trial divisions with some small primes.
*
* === Parameters
* * +checks+ - integer
......@@ -1001,7 +1037,8 @@ void
Init_ossl_bn(void)
{
#if 0
mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */
mOSSL = rb_define_module("OpenSSL");
eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
#endif
if (!(ossl_bn_ctx = BN_CTX_new())) {
......
......@@ -36,6 +36,7 @@
*/
VALUE cCipher;
VALUE eCipherError;
static ID id_auth_tag_len;
static VALUE ossl_cipher_alloc(VALUE klass);
static void ossl_cipher_free(void *ptr);
......@@ -54,11 +55,24 @@ static const rb_data_type_t ossl_cipher_type = {
const EVP_CIPHER *
GetCipherPtr(VALUE obj)
{
EVP_CIPHER_CTX *ctx;
if (rb_obj_is_kind_of(obj, cCipher)) {
EVP_CIPHER_CTX *ctx;
GetCipher(obj, ctx);
return EVP_CIPHER_CTX_cipher(ctx);
}
else {
const EVP_CIPHER *cipher;
SafeGetCipher(obj, ctx);
StringValueCStr(obj);
cipher = EVP_get_cipherbyname(RSTRING_PTR(obj));
if (!cipher)
ossl_raise(rb_eArgError,
"unsupported cipher algorithm: %"PRIsVALUE, obj);
return EVP_CIPHER_CTX_cipher(ctx);
return cipher;
}
}
VALUE
......@@ -248,7 +262,7 @@ ossl_cipher_init(int argc, VALUE *argv, VALUE self, int mode)
*
* Make sure to call Cipher#encrypt or Cipher#decrypt before using any of the
* following methods:
* * [key=, iv=, random_key, random_iv, pkcs5_keyivgen]
* * [#key=, #iv=, #random_key, #random_iv, #pkcs5_keyivgen]
*
* Internally calls EVP_CipherInit_ex(ctx, NULL, NULL, NULL, NULL, 1).
*/
......@@ -266,7 +280,7 @@ ossl_cipher_encrypt(int argc, VALUE *argv, VALUE self)
*
* Make sure to call Cipher#encrypt or Cipher#decrypt before using any of the
* following methods:
* * [key=, iv=, random_key, random_iv, pkcs5_keyivgen]
* * [#key=, #iv=, #random_key, #random_iv, #pkcs5_keyivgen]
*
* Internally calls EVP_CipherInit_ex(ctx, NULL, NULL, NULL, NULL, 0).
*/
......@@ -278,20 +292,20 @@ ossl_cipher_decrypt(int argc, VALUE *argv, VALUE self)
/*
* call-seq:
* cipher.pkcs5_keyivgen(pass [, salt [, iterations [, digest]]] ) -> nil
* cipher.pkcs5_keyivgen(pass, salt = nil, iterations = 2048, digest = "MD5") -> nil
*
* Generates and sets the key/IV based on a password.
*
* WARNING: This method is only PKCS5 v1.5 compliant when using RC2, RC4-40,
* *WARNING*: This method is only PKCS5 v1.5 compliant when using RC2, RC4-40,
* or DES with MD5 or SHA1. Using anything else (like AES) will generate the
* key/iv using an OpenSSL specific method. This method is deprecated and
* should no longer be used. Use a PKCS5 v2 key generation method from
* OpenSSL::PKCS5 instead.
*
* === Parameters
* +salt+ must be an 8 byte string if provided.
* +iterations+ is a integer with a default of 2048.
* +digest+ is a Digest object that defaults to 'MD5'
* * +salt+ must be an 8 byte string if provided.
* * +iterations+ is a integer with a default of 2048.
* * +digest+ is a Digest object that defaults to 'MD5'
*
* A minimum of 1000 iterations is recommended.
*
......@@ -331,25 +345,23 @@ ossl_cipher_update_long(EVP_CIPHER_CTX *ctx, unsigned char *out, long *out_len_p
const unsigned char *in, long in_len)
{
int out_part_len;
int limit = INT_MAX / 2 + 1;
long out_len = 0;
#define UPDATE_LENGTH_LIMIT INT_MAX
#if SIZEOF_LONG > UPDATE_LENGTH_LIMIT
if (in_len > UPDATE_LENGTH_LIMIT) {
const int in_part_len = (UPDATE_LENGTH_LIMIT / 2 + 1) & ~1;
do {
if (!EVP_CipherUpdate(ctx, out ? (out + out_len) : 0,
&out_part_len, in, in_part_len))
return 0;
out_len += out_part_len;
in += in_part_len;
} while ((in_len -= in_part_len) > UPDATE_LENGTH_LIMIT);
}
#endif
if (!EVP_CipherUpdate(ctx, out ? (out + out_len) : 0,
&out_part_len, in, (int)in_len))
return 0;
if (out_len_ptr) *out_len_ptr = out_len += out_part_len;
do {
int in_part_len = in_len > limit ? limit : (int)in_len;
if (!EVP_CipherUpdate(ctx, out ? (out + out_len) : 0,
&out_part_len, in, in_part_len))
return 0;
out_len += out_part_len;
in += in_part_len;
} while ((in_len -= limit) > 0);
if (out_len_ptr)
*out_len_ptr = out_len;
return 1;
}
......@@ -362,9 +374,8 @@ ossl_cipher_update_long(EVP_CIPHER_CTX *ctx, unsigned char *out, long *out_len_p
* data chunk. When done, the output of Cipher#final should be additionally
* added to the result.
*
* === Parameters
* +data+ is a nonempty string.
* +buffer+ is an optional string to store the result.
* If +buffer+ is given, the encryption/decryption result will be written to
* it. +buffer+ will be resized automatically.
*/
static VALUE
ossl_cipher_update(int argc, VALUE *argv, VALUE self)
......@@ -499,12 +510,17 @@ static VALUE
ossl_cipher_set_iv(VALUE self, VALUE iv)
{
EVP_CIPHER_CTX *ctx;
int iv_len;
int iv_len = 0;
StringValue(iv);
GetCipher(self, ctx);
iv_len = EVP_CIPHER_CTX_iv_length(ctx);
#if defined(HAVE_AUTHENTICATED_ENCRYPTION)
if (EVP_CIPHER_CTX_flags(ctx) & EVP_CIPH_FLAG_AEAD_CIPHER)
iv_len = (int)(VALUE)EVP_CIPHER_CTX_get_app_data(ctx);
#endif
if (!iv_len)
iv_len = EVP_CIPHER_CTX_iv_length(ctx);
if (RSTRING_LEN(iv) != iv_len)
ossl_raise(rb_eArgError, "iv must be %d bytes", iv_len);
......@@ -562,8 +578,9 @@ ossl_cipher_set_auth_data(VALUE self, VALUE data)
* then set on the decryption cipher to authenticate the contents of the
* ciphertext against changes. If the optional integer parameter +tag_len+ is
* given, the returned tag will be +tag_len+ bytes long. If the parameter is
* omitted, the maximum length of 16 bytes will be returned. For maximum
* security, the default of 16 bytes should be chosen.
* omitted, the default length of 16 bytes or the length previously set by
* #auth_tag_len= will be used. For maximum security, the longest possible
* should be chosen.
*
* The tag may only be retrieved after calling Cipher#final.
*/
......@@ -574,7 +591,10 @@ ossl_cipher_get_auth_tag(int argc, VALUE *argv, VALUE self)
EVP_CIPHER_CTX *ctx;
int tag_len = 16;
if (rb_scan_args(argc, argv, "01", &vtag_len) == 1)
rb_scan_args(argc, argv, "01", &vtag_len);
if (NIL_P(vtag_len))
vtag_len = rb_attr_get(self, id_auth_tag_len);
if (!NIL_P(vtag_len))
tag_len = NUM2INT(vtag_len);
GetCipher(self, ctx);
......@@ -600,6 +620,9 @@ ossl_cipher_get_auth_tag(int argc, VALUE *argv, VALUE self)
* decrypting any of the ciphertext. After all decryption is
* performed, the tag is verified automatically in the call to
* Cipher#final.
*
* For OCB mode, the tag length must be supplied with #auth_tag_len=
* beforehand.
*/
static VALUE
ossl_cipher_set_auth_tag(VALUE self, VALUE vtag)
......@@ -622,6 +645,36 @@ ossl_cipher_set_auth_tag(VALUE self, VALUE vtag)
return vtag;
}
/*
* call-seq:
* cipher.auth_tag_len = Integer -> Integer
*
* Sets the length of the authentication tag to be generated or to be given for
* AEAD ciphers that requires it as in input parameter. Note that not all AEAD
* ciphers support this method.
*
* In OCB mode, the length must be supplied both when encrypting and when
* decrypting, and must be before specifying an IV.
*/
static VALUE
ossl_cipher_set_auth_tag_len(VALUE self, VALUE vlen)
{
int tag_len = NUM2INT(vlen);
EVP_CIPHER_CTX *ctx;
GetCipher(self, ctx);
if (!(EVP_CIPHER_CTX_flags(ctx) & EVP_CIPH_FLAG_AEAD_CIPHER))
ossl_raise(eCipherError, "AEAD not supported by this cipher");
if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, tag_len, NULL))
ossl_raise(eCipherError, "unable to set authentication tag length");
/* for #auth_tag */
rb_ivar_set(self, id_auth_tag_len, INT2NUM(tag_len));
return vlen;
}
/*
* call-seq:
* cipher.authenticated? -> boolean
......@@ -638,11 +691,43 @@ ossl_cipher_is_authenticated(VALUE self)
return (EVP_CIPHER_CTX_flags(ctx) & EVP_CIPH_FLAG_AEAD_CIPHER) ? Qtrue : Qfalse;
}
/*
* call-seq:
* cipher.iv_len = integer -> integer
*
* Sets the IV/nonce length of the Cipher. Normally block ciphers don't allow
* changing the IV length, but some make use of IV for 'nonce'. You may need
* this for interoperability with other applications.
*/
static VALUE
ossl_cipher_set_iv_length(VALUE self, VALUE iv_length)
{
int len = NUM2INT(iv_length);
EVP_CIPHER_CTX *ctx;
GetCipher(self, ctx);
if (!(EVP_CIPHER_CTX_flags(ctx) & EVP_CIPH_FLAG_AEAD_CIPHER))
ossl_raise(eCipherError, "cipher does not support AEAD");
if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, len, NULL))
ossl_raise(eCipherError, "unable to set IV length");
/*
* EVP_CIPHER_CTX_iv_length() returns the default length. So we need to save
* the length somewhere. Luckily currently we aren't using app_data.
*/
EVP_CIPHER_CTX_set_app_data(ctx, (void *)(VALUE)len);
return iv_length;
}
#else
#define ossl_cipher_set_auth_data rb_f_notimplement
#define ossl_cipher_get_auth_tag rb_f_notimplement
#define ossl_cipher_set_auth_tag rb_f_notimplement
#define ossl_cipher_set_auth_tag_len rb_f_notimplement
#define ossl_cipher_is_authenticated rb_f_notimplement
#define ossl_cipher_set_iv_length rb_f_notimplement
#endif
/*
......@@ -692,36 +777,60 @@ ossl_cipher_set_padding(VALUE self, VALUE padding)
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))); \
}
/*
* call-seq:
* cipher.key_len -> integer
*
* Returns the key length in bytes of the Cipher.
*/
CIPHER_0ARG_INT(key_length)
static VALUE
ossl_cipher_key_length(VALUE self)
{
EVP_CIPHER_CTX *ctx;
GetCipher(self, ctx);
return INT2NUM(EVP_CIPHER_CTX_key_length(ctx));
}
/*
* call-seq:
* cipher.iv_len -> integer
*
* Returns the expected length in bytes for an IV for this Cipher.
*/
CIPHER_0ARG_INT(iv_length)
static VALUE
ossl_cipher_iv_length(VALUE self)
{
EVP_CIPHER_CTX *ctx;
int len = 0;
GetCipher(self, ctx);
#if defined(HAVE_AUTHENTICATED_ENCRYPTION)
if (EVP_CIPHER_CTX_flags(ctx) & EVP_CIPH_FLAG_AEAD_CIPHER)
len = (int)(VALUE)EVP_CIPHER_CTX_get_app_data(ctx);
#endif
if (!len)
len = EVP_CIPHER_CTX_iv_length(ctx);
return INT2NUM(len);
}
/*
* call-seq:
* cipher.block_size -> integer
*
* Returns the size in bytes of the blocks on which this Cipher operates on.
*/
CIPHER_0ARG_INT(block_size)
static VALUE
ossl_cipher_block_size(VALUE self)
{
EVP_CIPHER_CTX *ctx;
GetCipher(self, ctx);
return INT2NUM(EVP_CIPHER_CTX_block_size(ctx));
}
/*
* INIT
......@@ -730,7 +839,8 @@ void
Init_ossl_cipher(void)
{
#if 0
mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */
mOSSL = rb_define_module("OpenSSL");
eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
#endif
/* Document-class: OpenSSL::Cipher
......@@ -843,16 +953,16 @@ Init_ossl_cipher(void)
* of the IV as a nonce (number used once) - it's public but random and
* unpredictable. A secure random IV can be created as follows
*
* cipher = ...
* cipher.encrypt
* key = cipher.random_key
* iv = cipher.random_iv # also sets the generated IV on the Cipher
* cipher = ...
* cipher.encrypt
* key = cipher.random_key
* iv = cipher.random_iv # also sets the generated IV on the Cipher
*
* Although the key is generally a random value, too, it is a bad choice
* as an IV. There are elaborate ways how an attacker can take advantage
* of such an IV. As a general rule of thumb, exposing the key directly
* or indirectly should be avoided at all cost and exceptions only be
* made with good reason.
* Although the key is generally a random value, too, it is a bad choice
* as an IV. There are elaborate ways how an attacker can take advantage
* of such an IV. As a general rule of thumb, exposing the key directly
* or indirectly should be avoided at all cost and exceptions only be
* made with good reason.
*
* === Calling Cipher#final
*
......@@ -906,29 +1016,42 @@ Init_ossl_cipher(void)
* could otherwise be exploited to modify ciphertexts in ways beneficial to
* potential attackers.
*
* If no associated data is needed for encryption and later decryption,
* the OpenSSL library still requires a value to be set - "" may be used in
* case none is available. An example using the GCM (Galois Counter Mode):
* An associated data is used where there is additional information, such as
* headers or some metadata, that must be also authenticated but not
* necessarily need to be encrypted. If no associated data is needed for
* encryption and later decryption, the OpenSSL library still requires a
* value to be set - "" may be used in case none is available.
*
* cipher = OpenSSL::Cipher.new("aes-128-gcm")
* cipher.encrypt
* key = cipher.random_key
* iv = cipher.random_iv
* cipher.auth_data = ""
* An example using the GCM (Galois/Counter Mode). You have 16 bytes +key+,
* 12 bytes (96 bits) +nonce+ and the associated data +auth_data+. Be sure
* not to reuse the +key+ and +nonce+ pair. Reusing an nonce ruins the
* security gurantees of GCM mode.
*
* cipher = OpenSSL::Cipher::AES.new(128, :GCM).encrypt
* cipher.key = key
* cipher.iv = nonce
* cipher.auth_data = auth_data
*
* encrypted = cipher.update(data) + cipher.final
* tag = cipher.auth_tag
* tag = cipher.auth_tag # produces 16 bytes tag by default
*
* decipher = OpenSSL::Cipher.new("aes-128-gcm")
* decipher.decrypt
* Now you are the receiver. You know the +key+ and have received +nonce+,
* +auth_data+, +encrypted+ and +tag+ through an untrusted network. Note
* that GCM accepts an arbitrary length tag between 1 and 16 bytes. You may
* additionally need to check that the received tag has the correct length,
* or you allow attackers to forge a valid single byte tag for the tampered
* ciphertext with a probability of 1/256.
*
* raise "tag is truncated!" unless tag.bytesize == 16
* decipher = OpenSSL::Cipher::AES.new(128, :GCM).decrypt
* decipher.key = key
* decipher.iv = iv
* decipher.iv = nonce
* decipher.auth_tag = tag
* decipher.auth_data = ""
* decipher.auth_data = auth_data
*
* plain = decipher.update(encrypted) + decipher.final
* decrypted = decipher.update(encrypted) + decipher.final
*
* puts data == plain #=> true
* puts data == decrypted #=> true
*/
cCipher = rb_define_class_under(mOSSL, "Cipher", rb_cObject);
eCipherError = rb_define_class_under(cCipher, "CipherError", eOSSLError);
......@@ -948,11 +1071,15 @@ Init_ossl_cipher(void)
rb_define_method(cCipher, "auth_data=", ossl_cipher_set_auth_data, 1);
rb_define_method(cCipher, "auth_tag=", ossl_cipher_set_auth_tag, 1);
rb_define_method(cCipher, "auth_tag", ossl_cipher_get_auth_tag, -1);
rb_define_method(cCipher, "auth_tag_len=", ossl_cipher_set_auth_tag_len, 1);
rb_define_method(cCipher, "authenticated?", ossl_cipher_is_authenticated, 0);
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_set_iv_length, 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);
id_auth_tag_len = rb_intern_const("auth_tag_len");
}
......@@ -26,13 +26,13 @@ VALUE eConfigError;
*/
/*
* GetConfigPtr is a public C-level function for getting OpenSSL CONF struct
* DupConfigPtr 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)
DupConfigPtr(VALUE obj)
{
CONF *conf;
VALUE str;
......@@ -50,9 +50,10 @@ GetConfigPtr(VALUE obj)
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);
if (eline <= 0)
ossl_raise(eConfigError, "wrong config format");
else
ossl_raise(eConfigError, "error in line %d", eline);
}
BIO_free(bio);
......@@ -71,6 +72,12 @@ void
Init_ossl_config(void)
{
char *default_config_file;
#if 0
mOSSL = rb_define_module("OpenSSL");
eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
#endif
eConfigError = rb_define_class_under(mOSSL, "ConfigError", eOSSLError);
cConfig = rb_define_class_under(mOSSL, "Config", rb_cObject);
......
......@@ -13,7 +13,6 @@
extern VALUE cConfig;
extern VALUE eConfigError;
CONF* GetConfigPtr(VALUE obj);
CONF* DupConfigPtr(VALUE obj);
void Init_ossl_config(void);
......
......@@ -111,17 +111,16 @@ VALUE ossl_digest_update(VALUE, VALUE);
*
* Creates a Digest instance based on +string+, which is either the ln
* (long name) or sn (short name) of a supported digest algorithm.
*
* If +data+ (a +String+) is given, it is used as the initial input to the
* Digest instance, i.e.
*
* digest = OpenSSL::Digest.new('sha256', 'digestdata')
*
* is equal to
*
* digest = OpenSSL::Digest.new('sha256')
* digest.update('digestdata')
*
* === Example
* digest = OpenSSL::Digest.new('sha1')
*
*
*/
static VALUE
ossl_digest_initialize(int argc, VALUE *argv, VALUE self)
......@@ -203,7 +202,9 @@ ossl_digest_update(VALUE self, VALUE data)
StringValue(data);
GetDigest(self, ctx);
EVP_DigestUpdate(ctx, RSTRING_PTR(data), RSTRING_LEN(data));
if (!EVP_DigestUpdate(ctx, RSTRING_PTR(data), RSTRING_LEN(data)))
ossl_raise(eDigestError, "EVP_DigestUpdate");
return self;
}
......@@ -218,19 +219,21 @@ ossl_digest_finish(int argc, VALUE *argv, VALUE self)
{
EVP_MD_CTX *ctx;
VALUE str;
rb_scan_args(argc, argv, "01", &str);
int out_len;
GetDigest(self, ctx);
rb_scan_args(argc, argv, "01", &str);
out_len = EVP_MD_CTX_size(ctx);
if (NIL_P(str)) {
str = rb_str_new(NULL, EVP_MD_CTX_size(ctx));
str = rb_str_new(NULL, out_len);
} else {
StringValue(str);
rb_str_resize(str, EVP_MD_CTX_size(ctx));
rb_str_resize(str, out_len);
}
EVP_DigestFinal_ex(ctx, (unsigned char *)RSTRING_PTR(str), NULL);
if (!EVP_DigestFinal_ex(ctx, (unsigned char *)RSTRING_PTR(str), NULL))
ossl_raise(eDigestError, "EVP_DigestFinal_ex");
return str;
}
......@@ -239,7 +242,7 @@ ossl_digest_finish(int argc, VALUE *argv, VALUE self)
* call-seq:
* digest.name -> string
*
* Returns the sn of this Digest instance.
* Returns the sn of this Digest algorithm.
*
* === Example
* digest = OpenSSL::Digest::SHA512.new
......@@ -310,7 +313,8 @@ Init_ossl_digest(void)
rb_require("digest");
#if 0
mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */
mOSSL = rb_define_module("OpenSSL");
eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
#endif
/* Document-class: OpenSSL::Digest
......
......@@ -161,8 +161,6 @@ ossl_engine_s_load(int argc, VALUE *argv, VALUE klass)
* OpenSSL::Engine.load. However, running cleanup before exit is recommended.
*
* Note that this is needed and works only in OpenSSL < 1.1.0.
*
* See also, https://www.openssl.org/docs/crypto/engine.html
*/
static VALUE
ossl_engine_s_cleanup(VALUE self)
......@@ -531,6 +529,11 @@ ossl_engine_inspect(VALUE self)
void
Init_ossl_engine(void)
{
#if 0
mOSSL = rb_define_module("OpenSSL");
eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
#endif
cEngine = rb_define_class_under(mOSSL, "Engine", rb_cObject);
eEngineError = rb_define_class_under(cEngine, "EngineError", eOSSLError);
......@@ -540,6 +543,7 @@ Init_ossl_engine(void)
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_undef_method(cEngine, "initialize_copy");
rb_define_method(cEngine, "id", ossl_engine_get_id, 0);
rb_define_method(cEngine, "name", ossl_engine_get_name, 0);
......
......@@ -162,7 +162,7 @@ ossl_hmac_update(VALUE self, VALUE data)
}
static void
hmac_final(HMAC_CTX *ctx, unsigned char **buf, unsigned int *buf_len)
hmac_final(HMAC_CTX *ctx, unsigned char *buf, unsigned int *buf_len)
{
HMAC_CTX *final;
......@@ -175,12 +175,7 @@ hmac_final(HMAC_CTX *ctx, unsigned char **buf, unsigned int *buf_len)
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_Final(final, buf, buf_len);
HMAC_CTX_free(final);
}
......@@ -191,26 +186,25 @@ hmac_final(HMAC_CTX *ctx, unsigned char **buf, unsigned int *buf_len)
* 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?"
*
* 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;
VALUE ret;
GetHMAC(self, ctx);
hmac_final(ctx, &buf, &buf_len);
digest = ossl_buf2str((char *)buf, buf_len);
ret = rb_str_new(NULL, EVP_MAX_MD_SIZE);
hmac_final(ctx, (unsigned char *)RSTRING_PTR(ret), &buf_len);
assert(buf_len <= EVP_MAX_MD_SIZE);
rb_str_set_len(ret, buf_len);
return digest;
return ret;
}
/*
......@@ -219,27 +213,21 @@ ossl_hmac_digest(VALUE self)
*
* 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 char buf[EVP_MAX_MD_SIZE];
unsigned int buf_len;
VALUE hexdigest;
VALUE ret;
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);
hmac_final(ctx, buf, &buf_len);
ret = rb_str_new(NULL, buf_len * 2);
ossl_bin2hex(buf, RSTRING_PTR(ret), buf_len);
return hexdigest;
return ret;
}
/*
......@@ -323,22 +311,22 @@ ossl_hmac_s_digest(VALUE klass, VALUE digest, VALUE key, VALUE data)
static VALUE
ossl_hmac_s_hexdigest(VALUE klass, VALUE digest, VALUE key, VALUE data)
{
unsigned char *buf;
char *hexbuf;
unsigned char buf[EVP_MAX_MD_SIZE];
unsigned int buf_len;
VALUE hexdigest;
VALUE ret;
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);
if (!HMAC(GetDigestPtr(digest), RSTRING_PTR(key), RSTRING_LENINT(key),
(unsigned char *)RSTRING_PTR(data), RSTRING_LEN(data),
buf, &buf_len))
ossl_raise(eHMACError, "HMAC");
ret = rb_str_new(NULL, buf_len * 2);
ossl_bin2hex(buf, RSTRING_PTR(ret), buf_len);
return hexdigest;
return ret;
}
/*
......@@ -348,10 +336,38 @@ void
Init_ossl_hmac(void)
{
#if 0
/* :nodoc: */
mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */
mOSSL = rb_define_module("OpenSSL");
eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
#endif
/*
* Document-class: OpenSSL::HMAC
*
* OpenSSL::HMAC allows computing Hash-based Message Authentication Code
* (HMAC). It is a type of message authentication code (MAC) involving a
* hash function in combination with a key. HMAC can be used to verify the
* integrity of a message as well as the authenticity.
*
* OpenSSL::HMAC has a similar interface to OpenSSL::Digest.
*
* === HMAC-SHA256 using one-shot interface
*
* key = "key"
* data = "message-to-be-authenticated"
* mac = OpenSSL::HMAC.hexdigest("SHA256", key, data)
* #=> "cddb0db23f469c8bf072b21fd837149bd6ace9ab771cceef14c9e517cc93282e"
*
* === HMAC-SHA256 using incremental interface
*
* data1 = File.read("file1")
* data2 = File.read("file2")
* key = "key"
* digest = OpenSSL::Digest::SHA256.new
* hmac = OpenSSL::HMAC.new(key, digest)
* hmac << data1
* hmac << data2
* mac = hmac.digest
*/
eHMACError = rb_define_class_under(mOSSL, "HMACError", eOSSLError);
cHMAC = rb_define_class_under(mOSSL, "HMAC", rb_cObject);
......
......@@ -380,7 +380,8 @@ void
Init_ossl_ns_spki(void)
{
#if 0
mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */
mOSSL = rb_define_module("OpenSSL");
eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
#endif
mNetscape = rb_define_module_under(mOSSL, "Netscape");
......
......@@ -321,12 +321,17 @@ static VALUE
ossl_ocspreq_add_certid(VALUE self, VALUE certid)
{
OCSP_REQUEST *req;
OCSP_CERTID *id;
OCSP_CERTID *id, *id_new;
GetOCSPReq(self, req);
GetOCSPCertId(certid, id);
if(!OCSP_request_add0_id(req, OCSP_CERTID_dup(id)))
ossl_raise(eOCSPError, NULL);
if (!(id_new = OCSP_CERTID_dup(id)))
ossl_raise(eOCSPError, "OCSP_CERTID_dup");
if (!OCSP_request_add0_id(req, id_new)) {
OCSP_CERTID_free(id_new);
ossl_raise(eOCSPError, "OCSP_request_add0_id");
}
return self;
}
......@@ -368,14 +373,16 @@ ossl_ocspreq_get_certid(VALUE self)
*
* Signs this OCSP request using +cert+, +key+ and optional +digest+. If
* +digest+ is not specified, SHA-1 is used. +certs+ is an optional Array of
* additional certificates that will be included in the request. If +certs+ is
* not specified, flag OpenSSL::OCSP::NOCERTS is set. Pass an empty array to
* include only the signer certificate.
* additional certificates which are included in the request in addition to
* the signer certificate. Note that if +certs+ is nil or not given, flag
* OpenSSL::OCSP::NOCERTS is enabled. Pass an empty array to include only the
* signer certificate.
*
* +flags+ can include:
* OpenSSL::OCSP::NOCERTS:: don't include certificates
* +flags+ can be a bitwise OR of the following constants:
*
* OpenSSL::OCSP::NOCERTS::
* Don't include any certificates in the request. +certs+ will be ignored.
*/
static VALUE
ossl_ocspreq_sign(int argc, VALUE *argv, VALUE self)
{
......@@ -399,7 +406,7 @@ ossl_ocspreq_sign(int argc, VALUE *argv, VALUE self)
else
md = GetDigestPtr(digest);
if (NIL_P(certs))
flags |= OCSP_NOCERTS;
flg |= OCSP_NOCERTS;
else
x509s = ossl_x509_ary2sk(certs);
......@@ -435,7 +442,7 @@ ossl_ocspreq_verify(int argc, VALUE *argv, VALUE self)
x509s = ossl_x509_ary2sk(certs);
result = OCSP_request_verify(req, x509s, x509st, flg);
sk_X509_pop_free(x509s, X509_free);
if (!result)
if (result <= 0)
ossl_clear_error();
return result > 0 ? Qtrue : Qfalse;
......@@ -856,13 +863,11 @@ ossl_ocspbres_add_status(VALUE self, VALUE cid, VALUE status,
X509_EXTENSION *x509ext;
for(i = 0; i < RARRAY_LEN(ext); i++){
x509ext = DupX509ExtPtr(RARRAY_AREF(ext, i));
x509ext = GetX509ExtPtr(RARRAY_AREF(ext, i));
if(!OCSP_SINGLERESP_add_ext(single, x509ext, -1)){
X509_EXTENSION_free(x509ext);
error = 1;
goto err;
}
X509_EXTENSION_free(x509ext);
}
}
......@@ -911,7 +916,7 @@ ossl_ocspbres_get_status(VALUE self)
status = OCSP_single_get0_status(single, &reason, &revtime,
&thisupd, &nextupd);
if(status < 0) continue;
if(!(cid = OCSP_CERTID_dup(OCSP_SINGLERESP_get0_id(single))))
if(!(cid = OCSP_CERTID_dup((OCSP_CERTID *)OCSP_SINGLERESP_get0_id(single)))) /* FIXME */
ossl_raise(eOCSPError, NULL);
ary = rb_ary_new();
rb_ary_push(ary, ossl_ocspcertid_new(cid));
......@@ -1065,9 +1070,57 @@ ossl_ocspbres_verify(int argc, VALUE *argv, VALUE self)
x509st = GetX509StorePtr(store);
flg = NIL_P(flags) ? 0 : NUM2INT(flags);
x509s = ossl_x509_ary2sk(certs);
#if (OPENSSL_VERSION_NUMBER < 0x1000202fL) || defined(LIBRESSL_VERSION_NUMBER)
/*
* OpenSSL had a bug that it doesn't use the certificates in x509s for
* verifying the chain. This can be a problem when the response is signed by
* a certificate issued by an intermediate CA.
*
* root_ca
* |
* intermediate_ca
* |-------------|
* end_entity ocsp_signer
*
* When the certificate hierarchy is like this, and the response contains
* only ocsp_signer certificate, the following code wrongly fails.
*
* store = OpenSSL::X509::Store.new; store.add_cert(root_ca)
* basic_response.verify([intermediate_ca], store)
*
* So add the certificates in x509s to the embedded certificates list first.
*
* This is fixed in OpenSSL 0.9.8zg, 1.0.0s, 1.0.1n, 1.0.2b. But it still
* exists in LibreSSL 2.1.10, 2.2.9, 2.3.6, 2.4.1.
*/
if (!(flg & (OCSP_NOCHAIN | OCSP_NOVERIFY)) &&
sk_X509_num(x509s) && sk_X509_num(bs->certs)) {
int i;
bs = ASN1_item_dup(ASN1_ITEM_rptr(OCSP_BASICRESP), bs);
if (!bs) {
sk_X509_pop_free(x509s, X509_free);
ossl_raise(eOCSPError, "ASN1_item_dup");
}
for (i = 0; i < sk_X509_num(x509s); i++) {
if (!OCSP_basic_add1_cert(bs, sk_X509_value(x509s, i))) {
sk_X509_pop_free(x509s, X509_free);
OCSP_BASICRESP_free(bs);
ossl_raise(eOCSPError, "OCSP_basic_add1_cert");
}
}
result = OCSP_basic_verify(bs, x509s, x509st, flg);
OCSP_BASICRESP_free(bs);
}
else {
result = OCSP_basic_verify(bs, x509s, x509st, flg);
}
#else
result = OCSP_basic_verify(bs, x509s, x509st, flg);
#endif
sk_X509_pop_free(x509s, X509_free);
if (!result)
if (result <= 0)
ossl_clear_error();
return result > 0 ? Qtrue : Qfalse;
......@@ -1228,7 +1281,7 @@ ossl_ocspsres_get_certid(VALUE self)
OCSP_CERTID *id;
GetOCSPSingleRes(self, sres);
id = OCSP_CERTID_dup(OCSP_SINGLERESP_get0_id(sres));
id = OCSP_CERTID_dup((OCSP_CERTID *)OCSP_SINGLERESP_get0_id(sres)); /* FIXME */
return ossl_ocspcertid_new(id);
}
......@@ -1549,15 +1602,15 @@ ossl_ocspcid_get_issuer_name_hash(VALUE self)
{
OCSP_CERTID *id;
ASN1_OCTET_STRING *name_hash;
char *hexbuf;
VALUE ret;
GetOCSPCertId(self, id);
OCSP_id_get0_info(&name_hash, NULL, NULL, NULL, id);
if (string2hex(name_hash->data, name_hash->length, &hexbuf, NULL) < 0)
ossl_raise(eOCSPError, "string2hex");
ret = rb_str_new(NULL, name_hash->length * 2);
ossl_bin2hex(name_hash->data, RSTRING_PTR(ret), name_hash->length);
return ossl_buf2str(hexbuf, name_hash->length * 2);
return ret;
}
/*
......@@ -1572,15 +1625,15 @@ ossl_ocspcid_get_issuer_key_hash(VALUE self)
{
OCSP_CERTID *id;
ASN1_OCTET_STRING *key_hash;
char *hexbuf;
VALUE ret;
GetOCSPCertId(self, id);
OCSP_id_get0_info(NULL, NULL, &key_hash, NULL, id);
if (string2hex(key_hash->data, key_hash->length, &hexbuf, NULL) < 0)
ossl_raise(eOCSPError, "string2hex");
ret = rb_str_new(NULL, key_hash->length * 2);
ossl_bin2hex(key_hash->data, RSTRING_PTR(ret), key_hash->length);
return ossl_buf2str(hexbuf, key_hash->length * 2);
return ret;
}
/*
......@@ -1639,6 +1692,11 @@ ossl_ocspcid_to_der(VALUE self)
void
Init_ossl_ocsp(void)
{
#if 0
mOSSL = rb_define_module("OpenSSL");
eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
#endif
/*
* OpenSSL::OCSP implements Online Certificate Status Protocol requests
* and responses.
......
......@@ -65,6 +65,25 @@ ossl_pkcs12_s_allocate(VALUE klass)
return obj;
}
static VALUE
ossl_pkcs12_initialize_copy(VALUE self, VALUE other)
{
PKCS12 *p12, *p12_old, *p12_new;
rb_check_frozen(self);
GetPKCS12(self, p12_old);
SafeGetPKCS12(other, p12);
p12_new = ASN1_dup((i2d_of_void *)i2d_PKCS12, (d2i_of_void *)d2i_PKCS12, (char *)p12);
if (!p12_new)
ossl_raise(ePKCS12Error, "ASN1_dup");
SetPKCS12(self, p12_new);
PKCS12_free(p12_old);
return self;
}
/*
* call-seq:
* PKCS12.create(pass, name, key, cert [, ca, [, key_pbe [, cert_pbe [, key_iter [, mac_iter [, keytype]]]]]])
......@@ -74,8 +93,8 @@ ossl_pkcs12_s_allocate(VALUE klass)
* * +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.
* * 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
......@@ -104,7 +123,6 @@ ossl_pkcs12_s_create(int argc, VALUE *argv, VALUE self)
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)
......@@ -122,6 +140,7 @@ ossl_pkcs12_s_create(int argc, VALUE *argv, VALUE self)
ktype = NUM2INT(keytype);
obj = NewPKCS12(cPKCS12);
x509s = NIL_P(ca) ? NULL : ossl_x509_ary2sk(ca);
p12 = PKCS12_create(passphrase, friendlyname, key, x509, x509s,
nkey, ncert, kiter, miter, ktype);
sk_X509_pop_free(x509s, X509_free);
......@@ -171,14 +190,14 @@ ossl_pkcs12_initialize(int argc, VALUE *argv, VALUE self)
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,
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);
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);
rb_protect((VALUE (*)(VALUE))ossl_x509_sk2ary, (VALUE)x509s, &st);
if(st) goto err;
}
......@@ -216,6 +235,11 @@ ossl_pkcs12_to_der(VALUE self)
void
Init_ossl_pkcs12(void)
{
#if 0
mOSSL = rb_define_module("OpenSSL");
eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
#endif
/*
* Defines a file format commonly used to store private keys with
* accompanying public key certificates, protected with a password-based
......@@ -226,6 +250,7 @@ Init_ossl_pkcs12(void)
rb_define_singleton_method(cPKCS12, "create", ossl_pkcs12_s_create, -1);
rb_define_alloc_func(cPKCS12, ossl_pkcs12_s_allocate);
rb_define_copy_func(cPKCS12, ossl_pkcs12_initialize_copy);
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);
......
......@@ -18,7 +18,7 @@ VALUE ePKCS5;
* * +keylen+ - integer
* * +digest+ - a string or OpenSSL::Digest object.
*
* Available in OpenSSL 0.9.4.
* Available in OpenSSL >= 1.0.0.
*
* Digests other than SHA1 may not be supported by other cryptography libraries.
*/
......@@ -60,7 +60,7 @@ ossl_pkcs5_pbkdf2_hmac(VALUE self, VALUE pass, VALUE salt, VALUE iter, VALUE key
*
* This method is available in almost any version of OpenSSL.
*
* Conforms to rfc2898.
* Conforms to RFC 2898.
*/
static VALUE
ossl_pkcs5_pbkdf2_hmac_sha1(VALUE self, VALUE pass, VALUE salt, VALUE iter, VALUE keylen)
......@@ -84,14 +84,10 @@ ossl_pkcs5_pbkdf2_hmac_sha1(VALUE self, VALUE pass, VALUE salt, VALUE iter, VALU
void
Init_ossl_pkcs5(void)
{
/*
* Password-based Encryption
*
*/
#if 0
mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */
#endif
#if 0
mOSSL = rb_define_module("OpenSSL");
eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
#endif
/* Document-class: OpenSSL::PKCS5
*
......@@ -104,7 +100,7 @@ Init_ossl_pkcs5(void)
*
* 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).
* already supports it (>= 1.0.0).
*
* === Parameters
* ==== Password
......
......@@ -772,7 +772,9 @@ ossl_pkcs7_verify(int argc, VALUE *argv, VALUE self)
VALUE data;
const char *msg;
GetPKCS7(self, p7);
rb_scan_args(argc, argv, "22", &certs, &store, &indata, &flags);
x509st = GetX509StorePtr(store);
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);
......@@ -784,8 +786,6 @@ ossl_pkcs7_verify(int argc, VALUE *argv, VALUE self)
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);
......@@ -793,13 +793,13 @@ ossl_pkcs7_verify(int argc, VALUE *argv, VALUE self)
}
ok = PKCS7_verify(p7, x509s, x509st, in, out, flg);
BIO_free(in);
if (ok < 0) ossl_raise(ePKCS7Error, NULL);
sk_X509_pop_free(x509s, X509_free);
if (ok < 0) ossl_raise(ePKCS7Error, "PKCS7_verify");
msg = ERR_reason_error_string(ERR_get_error());
ossl_pkcs7_set_err_string(self, msg ? rb_str_new2(msg) : Qnil);
ossl_clear_error();
data = ossl_membio2str(out);
ossl_pkcs7_set_data(self, data);
sk_X509_pop_free(x509s, X509_free);
return (ok == 1) ? Qtrue : Qfalse;
}
......@@ -839,12 +839,12 @@ ossl_pkcs7_add_data(VALUE self, VALUE data)
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);
}
in = ossl_obj2bio(data);
if(!(out = PKCS7_dataInit(pkcs7, NULL))) goto err;
for(;;){
if((len = BIO_read(in, buf, sizeof(buf))) <= 0)
......@@ -856,7 +856,7 @@ ossl_pkcs7_add_data(VALUE self, VALUE data)
ossl_pkcs7_set_data(self, Qnil);
err:
BIO_free(out);
BIO_free_all(out);
BIO_free(in);
if(ERR_peek_error()){
ossl_raise(ePKCS7Error, NULL);
......@@ -1054,6 +1054,11 @@ ossl_pkcs7ri_get_enc_key(VALUE self)
void
Init_ossl_pkcs7(void)
{
#if 0
mOSSL = rb_define_module("OpenSSL");
eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
#endif
cPKCS7 = rb_define_class_under(mOSSL, "PKCS7", rb_cObject);
ePKCS7Error = rb_define_class_under(cPKCS7, "PKCS7Error", eOSSLError);
rb_define_singleton_method(cPKCS7, "read_smime", ossl_pkcs7_s_read_smime, 1);
......
......@@ -15,7 +15,7 @@
VALUE mPKey;
VALUE cPKey;
VALUE ePKeyError;
ID id_private_q;
static ID id_private_q;
/*
* callback for generating keys
......@@ -123,16 +123,19 @@ ossl_pkey_new_from_file(VALUE filename)
/*
* call-seq:
* OpenSSL::PKey.read(string [, pwd ] ) -> PKey
* OpenSSL::PKey.read(file [, pwd ]) -> PKey
* OpenSSL::PKey.read(string [, pwd ]) -> PKey
* OpenSSL::PKey.read(io [, pwd ]) -> PKey
*
* Reads a DER or PEM encoded string from +string+ or +io+ and returns an
* instance of the appropriate PKey class.
*
* === Parameters
* * +string+ is a DER- or PEM-encoded string containing an arbitrary private
* or public key.
* * +file+ is an instance of +File+ containing a DER- or PEM-encoded
* arbitrary private or public key.
* or public key.
* * +io+ is an instance of +IO+ containing a DER- or PEM-encoded
* arbitrary private or public key.
* * +pwd+ is an optional password in case +string+ or +file+ is an encrypted
* PEM resource.
* PEM resource.
*/
static VALUE
ossl_pkey_new_from_data(int argc, VALUE *argv, VALUE self)
......@@ -158,7 +161,8 @@ ossl_pkey_new_from_data(int argc, VALUE *argv, VALUE self)
BIO_free(bio);
if (!pkey)
ossl_raise(rb_eArgError, "Could not parse PKey");
ossl_raise(ePKeyError, "Could not parse PKey");
return ossl_pkey_new(pkey);
}
......@@ -196,20 +200,6 @@ DupPKeyPtr(VALUE obj)
return pkey;
}
EVP_PKEY *
DupPrivPKeyPtr(VALUE obj)
{
EVP_PKEY *pkey;
if (rb_funcallv(obj, id_private_q, 0, NULL) != Qtrue) {
ossl_raise(rb_eArgError, "Private key is needed.");
}
SafeGetPKey(obj, pkey);
EVP_PKEY_up_ref(pkey);
return pkey;
}
/*
* Private
*/
......@@ -271,9 +261,7 @@ ossl_pkey_sign(VALUE self, VALUE digest, VALUE data)
VALUE str;
int result;
if (rb_funcallv(self, id_private_q, 0, NULL) != Qtrue)
ossl_raise(rb_eArgError, "Private key is needed.");
GetPKey(self, pkey);
pkey = GetPrivPKeyPtr(self);
md = GetDigestPtr(digest);
StringValue(data);
str = rb_str_new(0, EVP_PKEY_size(pkey)+16);
......@@ -336,6 +324,7 @@ ossl_pkey_verify(VALUE self, VALUE digest, VALUE sig, VALUE data)
EVP_MD_CTX_free(ctx);
switch (result) {
case 0:
ossl_clear_error();
return Qfalse;
case 1:
return Qtrue;
......@@ -352,7 +341,8 @@ void
Init_ossl_pkey(void)
{
#if 0
mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */
mOSSL = rb_define_module("OpenSSL");
eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
#endif
/* Document-module: OpenSSL::PKey
......
......@@ -13,7 +13,6 @@
extern VALUE mPKey;
extern VALUE cPKey;
extern VALUE ePKeyError;
extern ID id_private_q;
extern const rb_data_type_t ossl_evp_pkey_type;
#define OSSL_PKEY_SET_PRIVATE(obj) rb_iv_set((obj), "private", Qtrue)
......@@ -53,7 +52,6 @@ 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);
/*
......
......@@ -175,8 +175,10 @@ ossl_dh_s_generate(int argc, VALUE *argv, VALUE klass)
}
/*
* call-seq:
* DH.new([size [, generator] | string]) -> dh
* call-seq:
* DH.new -> dh
* DH.new(string) -> dh
* DH.new(size [, generator]) -> dh
*
* Either generates a DH instance from scratch or by reading already existing
* DH parameters from +string+. Note that when reading a DH instance from
......@@ -210,11 +212,11 @@ ossl_dh_initialize(int argc, VALUE *argv, VALUE self)
if(rb_scan_args(argc, argv, "02", &arg, &gen) == 0) {
dh = DH_new();
}
else if (FIXNUM_P(arg)) {
else if (RB_INTEGER_TYPE_P(arg)) {
if (!NIL_P(gen)) {
g = NUM2INT(gen);
}
if (!(dh = dh_generate(FIX2INT(arg), g))) {
if (!(dh = dh_generate(NUM2INT(arg), g))) {
ossl_raise(eDHError, NULL);
}
}
......@@ -525,7 +527,7 @@ ossl_dh_generate_key(VALUE self)
*
* === Parameters
* * +pub_bn+ is a OpenSSL::BN, *not* the DH instance returned by
* DH#public_key as that contains the DH parameters only.
* DH#public_key as that contains the DH parameters only.
*/
static VALUE
ossl_dh_compute_key(VALUE self, VALUE pub)
......@@ -550,7 +552,21 @@ ossl_dh_compute_key(VALUE self, VALUE pub)
return str;
}
/*
* Document-method: OpenSSL::PKey::DH#set_pqg
* call-seq:
* dh.set_pqg(p, q, g) -> self
*
* Sets +p+, +q+, +g+ for the DH instance.
*/
OSSL_PKEY_BN_DEF3(dh, DH, pqg, p, q, g)
/*
* Document-method: OpenSSL::PKey::DH#set_key
* call-seq:
* dh.set_key(pub_key, priv_key) -> self
*
* Sets +pub_key+ and +priv_key+ for the DH instance. +priv_key+ may be nil.
*/
OSSL_PKEY_BN_DEF2(dh, DH, key, pub_key, priv_key)
/*
......@@ -560,8 +576,9 @@ void
Init_ossl_dh(void)
{
#if 0
mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL and mPKey */
mPKey = rb_define_module_under(mOSSL, "PKey");
cPKey = rb_define_class_under(mPKey, "PKey", rb_cObject);
ePKeyError = rb_define_class_under(mPKey, "PKeyError", eOSSLError);
#endif
/* Document-class: OpenSSL::PKey::DHError
......@@ -578,15 +595,15 @@ Init_ossl_dh(void)
* on.
*
* === Accessor methods for the Diffie-Hellman parameters
* * DH#p
* The prime (an OpenSSL::BN) of the Diffie-Hellman parameters.
* * DH#g
* The generator (an OpenSSL::BN) g of the Diffie-Hellman parameters.
* * DH#pub_key
* The per-session public key (an OpenSSL::BN) matching the private key.
* This needs to be passed to DH#compute_key.
* * DH#priv_key
* The per-session private key, an OpenSSL::BN.
* DH#p::
* The prime (an OpenSSL::BN) of the Diffie-Hellman parameters.
* DH#g::
* The generator (an OpenSSL::BN) g of the Diffie-Hellman parameters.
* DH#pub_key::
* The per-session public key (an OpenSSL::BN) matching the private key.
* This needs to be passed to DH#compute_key.
* DH#priv_key::
* The per-session private key, an OpenSSL::BN.
*
* === Example of a key exchange
* dh1 = OpenSSL::PKey::DH.new(2048)
......
......@@ -95,8 +95,6 @@ ossl_dsa_new(EVP_PKEY *pkey)
struct dsa_blocking_gen_arg {
DSA *dsa;
int size;
unsigned char* seed;
int seed_len;
int *counter;
unsigned long *h;
BN_GENCB *cb;
......@@ -107,7 +105,8 @@ static void *
dsa_blocking_gen(void *arg)
{
struct dsa_blocking_gen_arg *gen = (struct dsa_blocking_gen_arg *)arg;
gen->result = DSA_generate_parameters_ex(gen->dsa, gen->size, gen->seed, gen->seed_len, gen->counter, gen->h, gen->cb);
gen->result = DSA_generate_parameters_ex(gen->dsa, gen->size, NULL, 0,
gen->counter, gen->h, gen->cb);
return 0;
}
......@@ -118,13 +117,9 @@ dsa_generate(int size)
struct dsa_blocking_gen_arg gen_arg;
DSA *dsa = DSA_new();
BN_GENCB *cb = BN_GENCB_new();
unsigned char seed[20];
int seed_len = 20, counter;
int counter;
unsigned long h;
if (RAND_bytes(seed, seed_len) <= 0)
return NULL;
if (!dsa || !cb) {
DSA_free(dsa);
BN_GENCB_free(cb);
......@@ -136,8 +131,6 @@ dsa_generate(int size)
BN_GENCB_set(cb, ossl_generate_cb_2, &cb_arg);
gen_arg.dsa = dsa;
gen_arg.size = size;
gen_arg.seed = seed;
gen_arg.seed_len = seed_len;
gen_arg.counter = &counter;
gen_arg.h = &h;
gen_arg.cb = cb;
......@@ -198,7 +191,9 @@ ossl_dsa_s_generate(VALUE klass, VALUE size)
/*
* call-seq:
* DSA.new([size | string [, pass]) -> dsa
* DSA.new -> dsa
* DSA.new(size) -> dsa
* DSA.new(string [, pass]) -> dsa
*
* Creates a new DSA instance by reading an existing key from +string+.
*
......@@ -226,8 +221,8 @@ ossl_dsa_initialize(int argc, VALUE *argv, VALUE self)
if(rb_scan_args(argc, argv, "02", &arg, &pass) == 0) {
dsa = DSA_new();
}
else if (FIXNUM_P(arg)) {
if (!(dsa = dsa_generate(FIX2INT(arg)))) {
else if (RB_INTEGER_TYPE_P(arg)) {
if (!(dsa = dsa_generate(NUM2INT(arg)))) {
ossl_raise(eDSAError, NULL);
}
}
......@@ -387,14 +382,14 @@ static VALUE
ossl_dsa_to_der(VALUE self)
{
DSA *dsa;
int (*i2d_func)_((DSA*, unsigned char**));
int (*i2d_func)(DSA *, unsigned char **);
unsigned char *p;
long len;
VALUE str;
GetDSA(self, dsa);
if(DSA_HAS_PRIVATE(dsa))
i2d_func = (int(*)_((DSA*,unsigned char**)))i2d_DSAPrivateKey;
i2d_func = (int (*)(DSA *,unsigned char **))i2d_DSAPrivateKey;
else
i2d_func = i2d_DSA_PUBKEY;
if((len = i2d_func(dsa, NULL)) <= 0)
......@@ -592,7 +587,21 @@ ossl_dsa_verify(VALUE self, VALUE digest, VALUE sig)
return Qfalse;
}
/*
* Document-method: OpenSSL::PKey::DSA#set_pqg
* call-seq:
* dsa.set_pqg(p, q, g) -> self
*
* Sets +p+, +q+, +g+ for the DSA instance.
*/
OSSL_PKEY_BN_DEF3(dsa, DSA, pqg, p, q, g)
/*
* Document-method: OpenSSL::PKey::DSA#set_key
* call-seq:
* dsa.set_key(pub_key, priv_key) -> self
*
* Sets +pub_key+ and +priv_key+ for the DSA instance. +priv_key+ may be nil.
*/
OSSL_PKEY_BN_DEF2(dsa, DSA, key, pub_key, priv_key)
/*
......@@ -602,8 +611,9 @@ void
Init_ossl_dsa(void)
{
#if 0
mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL and mPKey */
mPKey = rb_define_module_under(mOSSL, "PKey");
cPKey = rb_define_class_under(mPKey, "PKey", rb_cObject);
ePKeyError = rb_define_class_under(mPKey, "PKeyError", eOSSLError);
#endif
/* Document-class: OpenSSL::PKey::DSAError
......
此差异已折叠。
......@@ -229,8 +229,8 @@ ossl_rsa_initialize(int argc, VALUE *argv, VALUE self)
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 : NUM2ULONG(pass));
else if (RB_INTEGER_TYPE_P(arg)) {
rsa = rsa_generate(NUM2INT(arg), NIL_P(pass) ? RSA_F4 : NUM2ULONG(pass));
if (!rsa) ossl_raise(eRSAError, NULL);
}
else {
......@@ -335,7 +335,7 @@ ossl_rsa_is_private(VALUE self)
*
* Outputs this keypair in PEM encoding. If +cipher+ and +pass_phrase+ are
* given they will be used to encrypt the key. +cipher+ must be an
* OpenSSL::Cipher::Cipher instance.
* OpenSSL::Cipher instance.
*/
static VALUE
ossl_rsa_export(int argc, VALUE *argv, VALUE self)
......@@ -383,7 +383,7 @@ static VALUE
ossl_rsa_to_der(VALUE self)
{
RSA *rsa;
int (*i2d_func)_((const RSA*, unsigned char**));
int (*i2d_func)(const RSA *, unsigned char **);
unsigned char *p;
long len;
VALUE str;
......@@ -392,7 +392,7 @@ ossl_rsa_to_der(VALUE self)
if (RSA_HAS_PRIVATE(rsa))
i2d_func = i2d_RSAPrivateKey;
else
i2d_func = (int (*)(const RSA*, unsigned char**))i2d_RSA_PUBKEY;
i2d_func = (int (*)(const RSA *, unsigned char **))i2d_RSA_PUBKEY;
if((len = i2d_func(rsa, NULL)) <= 0)
ossl_raise(eRSAError, NULL);
str = rb_str_new(0, len);
......@@ -656,21 +656,45 @@ ossl_rsa_blinding_off(VALUE self)
}
*/
/*
* Document-method: OpenSSL::PKey::RSA#set_key
* call-seq:
* rsa.set_key(n, e, d) -> self
*
* Sets +n+, +e+, +d+ for the RSA instance.
*/
OSSL_PKEY_BN_DEF3(rsa, RSA, key, n, e, d)
/*
* Document-method: OpenSSL::PKey::RSA#set_factors
* call-seq:
* rsa.set_factors(p, q) -> self
*
* Sets +p+, +q+ for the RSA instance.
*/
OSSL_PKEY_BN_DEF2(rsa, RSA, factors, p, q)
/*
* Document-method: OpenSSL::PKey::RSA#set_crt_params
* call-seq:
* rsa.set_crt_params(dmp1, dmq1, iqmp) -> self
*
* Sets +dmp1+, +dmq1+, +iqmp+ for the RSA instance. They are calculated by
* <tt>d mod (p - 1)</tt>, <tt>d mod (q - 1)</tt> and <tt>q^(-1) mod p</tt>
* respectively.
*/
OSSL_PKEY_BN_DEF3(rsa, RSA, crt_params, dmp1, dmq1, iqmp)
/*
* INIT
*/
#define DefRSAConst(x) rb_define_const(cRSA, #x,INT2FIX(RSA_##x))
#define DefRSAConst(x) rb_define_const(cRSA, #x, INT2NUM(RSA_##x))
void
Init_ossl_rsa(void)
{
#if 0
mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL and mPKey */
mPKey = rb_define_module_under(mOSSL, "PKey");
cPKey = rb_define_class_under(mPKey, "PKey", rb_cObject);
ePKeyError = rb_define_class_under(mPKey, "PKeyError", eOSSLError);
#endif
/* Document-class: OpenSSL::PKey::RSAError
......
......@@ -41,13 +41,13 @@ ossl_rand_seed(VALUE self, VALUE str)
* The +entropy+ argument is (the lower bound of) an estimate of how much
* randomness is contained in +str+, measured in bytes.
*
* Example:
* === Example
*
* pid = $$
* now = Time.now
* ary = [now.to_i, now.nsec, 1000, pid]
* OpenSSL::Random.add(ary.join("").to_s, 0.0)
* OpenSSL::Random.seed(ary.join("").to_s)
* OpenSSL::Random.add(ary.join, 0.0)
* OpenSSL::Random.seed(ary.join)
*/
static VALUE
ossl_rand_add(VALUE self, VALUE str, VALUE entropy)
......@@ -101,10 +101,10 @@ ossl_rand_write_file(VALUE self, VALUE filename)
* Generates +string+ with +length+ number of cryptographically strong
* pseudo-random bytes.
*
* Example:
* === Example
*
* OpenSSL::Random.random_bytes(12)
* => "..."
* #=> "..."
*/
static VALUE
ossl_rand_bytes(VALUE self, VALUE len)
......@@ -134,10 +134,10 @@ ossl_rand_bytes(VALUE self, VALUE len)
* Pseudo-random byte sequences generated by ::pseudo_bytes will be unique if
* they are of sufficient length, but are not necessarily unpredictable.
*
* Example:
* === Example
*
* OpenSSL::Random.pseudo_bytes(12)
* => "..."
* #=> "..."
*/
static VALUE
ossl_rand_pseudo_bytes(VALUE self, VALUE len)
......@@ -214,7 +214,8 @@ void
Init_ossl_rand(void)
{
#if 0
mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */
mOSSL = rb_define_module("OpenSSL");
eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
#endif
mRandom = rb_define_module_under(mOSSL, "Random");
......
此差异已折叠。
......@@ -28,12 +28,12 @@ static VALUE ossl_ssl_session_alloc(VALUE klass)
/*
* call-seq:
* Session.new(SSLSocket | string) => session
* Session.new(ssl_socket) -> Session
* Session.new(string) -> Session
*
* === Parameters
* +SSLSocket+ is an OpenSSL::SSL::SSLSocket
* +string+ must be a DER or PEM encoded Session.
*/
* Creates a new Session object from an instance of SSLSocket or DER/PEM encoded
* String.
*/
static VALUE ossl_ssl_session_initialize(VALUE self, VALUE arg1)
{
SSL_SESSION *ctx = NULL;
......@@ -73,6 +73,26 @@ static VALUE ossl_ssl_session_initialize(VALUE self, VALUE arg1)
return self;
}
static VALUE
ossl_ssl_session_initialize_copy(VALUE self, VALUE other)
{
SSL_SESSION *sess, *sess_other, *sess_new;
rb_check_frozen(self);
sess = RTYPEDDATA_DATA(self); /* XXX */
SafeGetSSLSession(other, sess_other);
sess_new = ASN1_dup((i2d_of_void *)i2d_SSL_SESSION, (d2i_of_void *)d2i_SSL_SESSION,
(char *)sess_other);
if (!sess_new)
ossl_raise(eSSLSession, "ASN1_dup");
RTYPEDDATA_DATA(self) = sess_new;
SSL_SESSION_free(sess);
return self;
}
#if HAVE_SSL_SESSION_CMP == 0
int SSL_SESSION_cmp(const SSL_SESSION *a,const SSL_SESSION *b)
{
......@@ -98,9 +118,10 @@ int SSL_SESSION_cmp(const SSL_SESSION *a,const SSL_SESSION *b)
/*
* call-seq:
* session1 == session2 -> boolean
* session1 == session2 -> boolean
*
*/
* Returns true if the two Session is the same, false if not.
*/
static VALUE ossl_ssl_session_eq(VALUE val1, VALUE val2)
{
SSL_SESSION *ctx1, *ctx2;
......@@ -118,9 +139,8 @@ static VALUE ossl_ssl_session_eq(VALUE val1, VALUE val2)
* call-seq:
* session.time -> Time
*
* Gets start time of the session.
*
*/
* Returns the time at which the session was established.
*/
static VALUE ossl_ssl_session_get_time(VALUE self)
{
SSL_SESSION *ctx;
......@@ -138,11 +158,12 @@ static VALUE ossl_ssl_session_get_time(VALUE self)
/*
* call-seq:
* session.timeout -> integer
* session.timeout -> Integer
*
* Gets how long until the session expires in seconds.
* Returns the timeout value set for the session, in seconds from the
* established time.
*
*/
*/
static VALUE ossl_ssl_session_get_timeout(VALUE self)
{
SSL_SESSION *ctx;
......@@ -157,12 +178,12 @@ static VALUE ossl_ssl_session_get_timeout(VALUE self)
/*
* call-seq:
* session.time=(Time) -> Time
* session.time=(integer) -> Time
* session.time = time
* session.time = integer
*
* Sets start time of the session. Time resolution is in seconds.
*
*/
*/
static VALUE ossl_ssl_session_set_time(VALUE self, VALUE time_v)
{
SSL_SESSION *ctx;
......@@ -179,11 +200,10 @@ static VALUE ossl_ssl_session_set_time(VALUE self, VALUE time_v)
/*
* call-seq:
* session.timeout=(integer) -> integer
* session.timeout = integer
*
* Sets how long until the session expires in seconds.
*
*/
*/
static VALUE ossl_ssl_session_set_timeout(VALUE self, VALUE time_v)
{
SSL_SESSION *ctx;
......@@ -197,7 +217,7 @@ static VALUE ossl_ssl_session_set_timeout(VALUE self, VALUE time_v)
/*
* call-seq:
* session.id -> aString
* session.id -> String
*
* Returns the Session ID.
*/
......@@ -216,10 +236,10 @@ static VALUE ossl_ssl_session_get_id(VALUE self)
/*
* call-seq:
* session.to_der -> aString
* session.to_der -> String
*
* Returns an ASN1 encoded String that contains the Session object.
*/
*/
static VALUE ossl_ssl_session_to_der(VALUE self)
{
SSL_SESSION *ctx;
......@@ -245,7 +265,7 @@ static VALUE ossl_ssl_session_to_der(VALUE self)
* session.to_pem -> String
*
* Returns a PEM encoded String that contains the Session object.
*/
*/
static VALUE ossl_ssl_session_to_pem(VALUE self)
{
SSL_SESSION *ctx;
......@@ -277,8 +297,8 @@ static VALUE ossl_ssl_session_to_pem(VALUE self)
* call-seq:
* session.to_text -> String
*
* Shows everything in the Session object.
*/
* Shows everything in the Session object. This is for diagnostic purposes.
*/
static VALUE ossl_ssl_session_to_text(VALUE self)
{
SSL_SESSION *ctx;
......@@ -308,14 +328,16 @@ static VALUE ossl_ssl_session_to_text(VALUE self)
void Init_ossl_ssl_session(void)
{
#if 0
mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */
mSSL = rb_define_module_under(mOSSL, "SSL");
mOSSL = rb_define_module("OpenSSL");
mSSL = rb_define_module_under(mOSSL, "SSL");
eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
#endif
cSSLSession = rb_define_class_under(mSSL, "Session", rb_cObject);
eSSLSession = rb_define_class_under(cSSLSession, "SessionError", eOSSLError);
rb_define_alloc_func(cSSLSession, ossl_ssl_session_alloc);
rb_define_method(cSSLSession, "initialize", ossl_ssl_session_initialize, 1);
rb_define_copy_func(cSSLSession, ossl_ssl_session_initialize_copy);
rb_define_method(cSSLSession, "==", ossl_ssl_session_eq, 1);
......
......@@ -10,6 +10,6 @@
#if !defined(_OSSL_VERSION_H_)
#define _OSSL_VERSION_H_
#define OSSL_VERSION "1.1.0"
#define OSSL_VERSION "2.0.0"
#endif /* _OSSL_VERSION_H_ */
......@@ -11,7 +11,7 @@
VALUE mX509;
#define DefX509Const(x) rb_define_const(mX509, #x,INT2FIX(X509_##x))
#define DefX509Const(x) rb_define_const(mX509, #x, INT2NUM(X509_##x))
#define DefX509Default(x,i) \
rb_define_const(mX509, "DEFAULT_" #x, rb_str_new2(X509_get_default_##i()))
......@@ -34,6 +34,10 @@ ossl_x509_time_adjust(ASN1_TIME *s, VALUE time)
void
Init_ossl_x509(void)
{
#if 0
mOSSL = rb_define_module("OpenSSL");
#endif
mX509 = rb_define_module_under(mOSSL, "X509");
Init_ossl_x509attr();
......@@ -79,17 +83,88 @@ Init_ossl_x509(void)
DefX509Const(V_ERR_KEYUSAGE_NO_CERTSIGN);
DefX509Const(V_ERR_APPLICATION_VERIFICATION);
/* Set by Store#flags= and StoreContext#flags=. Enables CRL checking for the
* certificate chain leaf. */
DefX509Const(V_FLAG_CRL_CHECK);
/* Set by Store#flags= and StoreContext#flags=. Enables CRL checking for all
* certificates in the certificate chain */
DefX509Const(V_FLAG_CRL_CHECK_ALL);
/* Set by Store#flags= and StoreContext#flags=. Disables critical extension
* checking. */
DefX509Const(V_FLAG_IGNORE_CRITICAL);
/* Set by Store#flags= and StoreContext#flags=. Disables workarounds for
* broken certificates. */
DefX509Const(V_FLAG_X509_STRICT);
/* Set by Store#flags= and StoreContext#flags=. Enables proxy certificate
* verification. */
DefX509Const(V_FLAG_ALLOW_PROXY_CERTS);
/* Set by Store#flags= and StoreContext#flags=. Enables certificate policy
* constraints checking. */
DefX509Const(V_FLAG_POLICY_CHECK);
/* Set by Store#flags= and StoreContext#flags=.
* Implies V_FLAG_POLICY_CHECK */
DefX509Const(V_FLAG_EXPLICIT_POLICY);
/* Set by Store#flags= and StoreContext#flags=.
* Implies V_FLAG_POLICY_CHECK */
DefX509Const(V_FLAG_INHIBIT_ANY);
/* Set by Store#flags= and StoreContext#flags=.
* Implies V_FLAG_POLICY_CHECK */
DefX509Const(V_FLAG_INHIBIT_MAP);
/* Set by Store#flags= and StoreContext#flags=. */
DefX509Const(V_FLAG_NOTIFY_POLICY);
#if defined(X509_V_FLAG_EXTENDED_CRL_SUPPORT)
/* Set by Store#flags= and StoreContext#flags=. Enables some additional
* features including support for indirect signed CRLs. */
DefX509Const(V_FLAG_EXTENDED_CRL_SUPPORT);
#endif
#if defined(X509_V_FLAG_USE_DELTAS)
/* Set by Store#flags= and StoreContext#flags=. Uses delta CRLs. If not
* specified, deltas are ignored. */
DefX509Const(V_FLAG_USE_DELTAS);
#endif
#if defined(X509_V_FLAG_CHECK_SS_SIGNATURE)
/* Set by Store#flags= and StoreContext#flags=. Enables checking of the
* signature of the root self-signed CA. */
DefX509Const(V_FLAG_CHECK_SS_SIGNATURE);
#endif
#if defined(X509_V_FLAG_TRUSTED_FIRST)
/* Set by Store#flags= and StoreContext#flags=. When constructing a
* certificate chain, search the Store first for the issuer certificate.
* Enabled by default in OpenSSL >= 1.1.0. */
DefX509Const(V_FLAG_TRUSTED_FIRST);
#endif
#if defined(X509_V_FLAG_NO_ALT_CHAINS)
/* Set by Store#flags= and StoreContext#flags=. Suppresses searching for
* a alternative chain. No effect in OpenSSL >= 1.1.0. */
DefX509Const(V_FLAG_NO_ALT_CHAINS);
#endif
#if defined(X509_V_FLAG_NO_CHECK_TIME)
/* Set by Store#flags= and StoreContext#flags=. Suppresses checking the
* validity period of certificates and CRLs. No effect when the current
* time is explicitly set by Store#time= or StoreContext#time=. */
DefX509Const(V_FLAG_NO_CHECK_TIME);
#endif
/* Set by Store#purpose=. SSL/TLS client. */
DefX509Const(PURPOSE_SSL_CLIENT);
/* Set by Store#purpose=. SSL/TLS server. */
DefX509Const(PURPOSE_SSL_SERVER);
/* Set by Store#purpose=. Netscape SSL server. */
DefX509Const(PURPOSE_NS_SSL_SERVER);
/* Set by Store#purpose=. S/MIME signing. */
DefX509Const(PURPOSE_SMIME_SIGN);
/* Set by Store#purpose=. S/MIME encryption. */
DefX509Const(PURPOSE_SMIME_ENCRYPT);
/* Set by Store#purpose=. CRL signing */
DefX509Const(PURPOSE_CRL_SIGN);
/* Set by Store#purpose=. No checks. */
DefX509Const(PURPOSE_ANY);
/* Set by Store#purpose=. OCSP helper. */
DefX509Const(PURPOSE_OCSP_HELPER);
#if defined(X509_PURPOSE_TIMESTAMP_SIGN)
/* Set by Store#purpose=. Time stamps signer. */
DefX509Const(PURPOSE_TIMESTAMP_SIGN);
#endif
DefX509Const(TRUST_COMPAT);
DefX509Const(TRUST_SSL_CLIENT);
......@@ -98,6 +173,9 @@ Init_ossl_x509(void)
DefX509Const(TRUST_OBJECT_SIGN);
DefX509Const(TRUST_OCSP_SIGN);
DefX509Const(TRUST_OCSP_REQUEST);
#if defined(X509_TRUST_TSA)
DefX509Const(TRUST_TSA);
#endif
DefX509Default(CERT_AREA, cert_area);
DefX509Default(CERT_DIR, cert_dir);
......
......@@ -31,7 +31,7 @@ extern VALUE cX509Attr;
extern VALUE eX509AttrError;
VALUE ossl_x509attr_new(X509_ATTRIBUTE *);
X509_ATTRIBUTE *DupX509AttrPtr(VALUE);
X509_ATTRIBUTE *GetX509AttrPtr(VALUE);
void Init_ossl_x509attr(void);
/*
......@@ -66,7 +66,6 @@ extern VALUE eX509ExtError;
VALUE ossl_x509ext_new(X509_EXTENSION *);
X509_EXTENSION *GetX509ExtPtr(VALUE);
X509_EXTENSION *DupX509ExtPtr(VALUE);
void Init_ossl_x509ext(void);
/*
......
......@@ -72,16 +72,13 @@ ossl_x509attr_new(X509_ATTRIBUTE *attr)
}
X509_ATTRIBUTE *
DupX509AttrPtr(VALUE obj)
GetX509AttrPtr(VALUE obj)
{
X509_ATTRIBUTE *attr, *new;
X509_ATTRIBUTE *attr;
SafeGetX509Attr(obj, attr);
if (!(new = X509_ATTRIBUTE_dup(attr))) {
ossl_raise(eX509AttrError, NULL);
}
return new;
return attr;
}
/*
......@@ -130,6 +127,25 @@ ossl_x509attr_initialize(int argc, VALUE *argv, VALUE self)
return self;
}
static VALUE
ossl_x509attr_initialize_copy(VALUE self, VALUE other)
{
X509_ATTRIBUTE *attr, *attr_other, *attr_new;
rb_check_frozen(self);
GetX509Attr(self, attr);
SafeGetX509Attr(other, attr_other);
attr_new = X509_ATTRIBUTE_dup(attr_other);
if (!attr_new)
ossl_raise(eX509AttrError, "X509_ATTRIBUTE_dup");
SetX509Attr(self, attr_new);
X509_ATTRIBUTE_free(attr);
return self;
}
/*
* call-seq:
* attr.oid = string => string
......@@ -141,12 +157,15 @@ ossl_x509attr_set_oid(VALUE self, VALUE oid)
ASN1_OBJECT *obj;
char *s;
GetX509Attr(self, attr);
s = StringValueCStr(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);
if (!X509_ATTRIBUTE_set1_object(attr, obj)) {
ASN1_OBJECT_free(obj);
ossl_raise(eX509AttrError, "X509_ATTRIBUTE_set1_object");
}
ASN1_OBJECT_free(obj);
return oid;
}
......@@ -289,11 +308,18 @@ ossl_x509attr_to_der(VALUE self)
void
Init_ossl_x509attr(void)
{
#if 0
mOSSL = rb_define_module("OpenSSL");
eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
mX509 = rb_define_module_under(mOSSL, "X509");
#endif
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_copy_func(cX509Attr, ossl_x509attr_initialize_copy);
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);
......
......@@ -456,10 +456,10 @@ static VALUE
ossl_x509_get_not_before(VALUE self)
{
X509 *x509;
ASN1_UTCTIME *asn1time;
const ASN1_TIME *asn1time;
GetX509(self, x509);
if (!(asn1time = X509_get_notBefore(x509))) { /* NO DUP - don't free! */
if (!(asn1time = X509_get0_notBefore(x509))) {
ossl_raise(eX509CertError, NULL);
}
......@@ -474,10 +474,15 @@ static VALUE
ossl_x509_set_not_before(VALUE self, VALUE time)
{
X509 *x509;
ASN1_TIME *asn1time;
GetX509(self, x509);
if (!ossl_x509_time_adjust(X509_get_notBefore(x509), time))
ossl_raise(eX509CertError, NULL);
asn1time = ossl_x509_time_adjust(NULL, time);
if (!X509_set_notBefore(x509, asn1time)) {
ASN1_TIME_free(asn1time);
ossl_raise(eX509CertError, "X509_set_notBefore");
}
ASN1_TIME_free(asn1time);
return time;
}
......@@ -490,10 +495,10 @@ static VALUE
ossl_x509_get_not_after(VALUE self)
{
X509 *x509;
ASN1_TIME *asn1time;
const ASN1_TIME *asn1time;
GetX509(self, x509);
if (!(asn1time = X509_get_notAfter(x509))) { /* NO DUP - don't free! */
if (!(asn1time = X509_get0_notAfter(x509))) {
ossl_raise(eX509CertError, NULL);
}
......@@ -508,10 +513,15 @@ static VALUE
ossl_x509_set_not_after(VALUE self, VALUE time)
{
X509 *x509;
ASN1_TIME *asn1time;
GetX509(self, x509);
if (!ossl_x509_time_adjust(X509_get_notAfter(x509), time))
ossl_raise(eX509CertError, NULL);
asn1time = ossl_x509_time_adjust(NULL, time);
if (!X509_set_notAfter(x509, asn1time)) {
ASN1_TIME_free(asn1time);
ossl_raise(eX509CertError, "X509_set_notAfter");
}
ASN1_TIME_free(asn1time);
return time;
}
......@@ -667,13 +677,10 @@ ossl_x509_set_extensions(VALUE self, VALUE ary)
while ((ext = X509_delete_ext(x509, 0)))
X509_EXTENSION_free(ext);
for (i=0; i<RARRAY_LEN(ary); i++) {
ext = DupX509ExtPtr(RARRAY_AREF(ary, i));
if (!X509_add_ext(x509, ext, -1)) { /* DUPs ext - FREE it */
X509_EXTENSION_free(ext);
ext = GetX509ExtPtr(RARRAY_AREF(ary, i));
if (!X509_add_ext(x509, ext, -1)) { /* DUPs ext */
ossl_raise(eX509CertError, NULL);
}
X509_EXTENSION_free(ext);
}
return ary;
......@@ -690,12 +697,10 @@ ossl_x509_add_extension(VALUE self, VALUE extension)
X509_EXTENSION *ext;
GetX509(self, x509);
ext = DupX509ExtPtr(extension);
ext = GetX509ExtPtr(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;
}
......@@ -720,9 +725,9 @@ ossl_x509_inspect(VALUE self)
void
Init_ossl_x509cert(void)
{
#if 0
mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */
mOSSL = rb_define_module("OpenSSL");
eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
mX509 = rb_define_module_under(mOSSL, "X509");
#endif
......
......@@ -180,7 +180,7 @@ static VALUE
ossl_x509crl_get_signature_algorithm(VALUE self)
{
X509_CRL *crl;
X509_ALGOR *alg;
const X509_ALGOR *alg;
BIO *out;
BUF_MEM *buf;
VALUE str;
......@@ -189,7 +189,7 @@ ossl_x509crl_get_signature_algorithm(VALUE self)
if (!(out = BIO_new(BIO_s_mem()))) {
ossl_raise(eX509CRLError, NULL);
}
X509_CRL_get0_signature(NULL, &alg, crl);
X509_CRL_get0_signature(crl, NULL, &alg);
if (!i2a_ASN1_OBJECT(out, alg->algorithm)) {
BIO_free(out);
ossl_raise(eX509CRLError, NULL);
......@@ -230,17 +230,22 @@ ossl_x509crl_get_last_update(VALUE self)
GetX509CRL(self, crl);
return asn1time_to_time(X509_CRL_get_lastUpdate(crl));
return asn1time_to_time(X509_CRL_get0_lastUpdate(crl));
}
static VALUE
ossl_x509crl_set_last_update(VALUE self, VALUE time)
{
X509_CRL *crl;
ASN1_TIME *asn1time;
GetX509CRL(self, crl);
if (!ossl_x509_time_adjust(X509_CRL_get_lastUpdate(crl), time))
ossl_raise(eX509CRLError, NULL);
asn1time = ossl_x509_time_adjust(NULL, time);
if (!X509_CRL_set_lastUpdate(crl, asn1time)) {
ASN1_TIME_free(asn1time);
ossl_raise(eX509CRLError, "X509_CRL_set_lastUpdate");
}
ASN1_TIME_free(asn1time);
return time;
}
......@@ -252,28 +257,22 @@ ossl_x509crl_get_next_update(VALUE self)
GetX509CRL(self, crl);
return asn1time_to_time(X509_CRL_get_nextUpdate(crl));
return asn1time_to_time(X509_CRL_get0_nextUpdate(crl));
}
static VALUE
ossl_x509crl_set_next_update(VALUE self, VALUE time)
{
X509_CRL *crl;
ASN1_TIME *orig, *new;
ASN1_TIME *asn1time;
GetX509CRL(self, crl);
/* orig may be NULL at this time; in this case a new ASN1_TIME is created */
orig = X509_CRL_get_nextUpdate(crl);
new = ossl_x509_time_adjust(orig, time);
if (!X509_CRL_set_nextUpdate(crl, new)) {
if (!orig)
ASN1_TIME_free(new);
ossl_raise(eX509CRLError, NULL);
asn1time = ossl_x509_time_adjust(NULL, time);
if (!X509_CRL_set_nextUpdate(crl, asn1time)) {
ASN1_TIME_free(asn1time);
ossl_raise(eX509CRLError, "X509_CRL_set_nextUpdate");
}
/* X509_CRL_set_nextUpdate() dups when orig != new */
if (!orig)
ASN1_TIME_free(new);
ASN1_TIME_free(asn1time);
return time;
}
......@@ -308,6 +307,7 @@ ossl_x509crl_set_revoked(VALUE self, VALUE ary)
{
X509_CRL *crl;
X509_REVOKED *rev;
STACK_OF(X509_REVOKED) *sk;
long i;
Check_Type(ary, T_ARRAY);
......@@ -316,11 +316,15 @@ ossl_x509crl_set_revoked(VALUE self, VALUE ary)
OSSL_Check_Kind(RARRAY_AREF(ary, i), cX509Rev);
}
GetX509CRL(self, crl);
sk_X509_REVOKED_pop_free(X509_CRL_get_REVOKED(crl), X509_REVOKED_free);
if ((sk = X509_CRL_get_REVOKED(crl))) {
while ((rev = sk_X509_REVOKED_pop(sk)))
X509_REVOKED_free(rev);
}
for (i=0; i<RARRAY_LEN(ary); i++) {
rev = DupX509RevokedPtr(RARRAY_AREF(ary, i));
if (!X509_CRL_add0_revoked(crl, rev)) { /* NO DUP - don't free! */
ossl_raise(eX509CRLError, NULL);
X509_REVOKED_free(rev);
ossl_raise(eX509CRLError, "X509_CRL_add0_revoked");
}
}
X509_CRL_sort(crl);
......@@ -337,7 +341,8 @@ ossl_x509crl_add_revoked(VALUE self, VALUE revoked)
GetX509CRL(self, crl);
rev = DupX509RevokedPtr(revoked);
if (!X509_CRL_add0_revoked(crl, rev)) { /* NO DUP - don't free! */
ossl_raise(eX509CRLError, NULL);
X509_REVOKED_free(rev);
ossl_raise(eX509CRLError, "X509_CRL_add0_revoked");
}
X509_CRL_sort(crl);
......@@ -492,12 +497,10 @@ ossl_x509crl_set_extensions(VALUE self, VALUE ary)
while ((ext = X509_CRL_delete_ext(crl, 0)))
X509_EXTENSION_free(ext);
for (i=0; i<RARRAY_LEN(ary); i++) {
ext = DupX509ExtPtr(RARRAY_AREF(ary, i));
if(!X509_CRL_add_ext(crl, ext, -1)) { /* DUPs ext - FREE it */
X509_EXTENSION_free(ext);
ext = GetX509ExtPtr(RARRAY_AREF(ary, i)); /* NO NEED TO DUP */
if (!X509_CRL_add_ext(crl, ext, -1)) {
ossl_raise(eX509CRLError, NULL);
}
X509_EXTENSION_free(ext);
}
return ary;
......@@ -510,12 +513,10 @@ ossl_x509crl_add_extension(VALUE self, VALUE extension)
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);
ext = GetX509ExtPtr(extension);
if (!X509_CRL_add_ext(crl, ext, -1)) {
ossl_raise(eX509CRLError, NULL);
}
X509_EXTENSION_free(ext);
return extension;
}
......@@ -526,6 +527,12 @@ ossl_x509crl_add_extension(VALUE self, VALUE extension)
void
Init_ossl_x509crl(void)
{
#if 0
mOSSL = rb_define_module("OpenSSL");
eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
mX509 = rb_define_module_under(mOSSL, "X509");
#endif
eX509CRLError = rb_define_class_under(mX509, "CRLError", eOSSLError);
cX509CRL = rb_define_class_under(mX509, "CRL", rb_cObject);
......
......@@ -95,19 +95,6 @@ GetX509ExtPtr(VALUE obj)
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
*/
......@@ -188,20 +175,6 @@ ossl_x509extfactory_set_crl(VALUE self, VALUE crl)
return crl;
}
static VALUE
ossl_x509extfactory_set_config(VALUE self, VALUE config)
{
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;
}
static VALUE
ossl_x509extfactory_initialize(int argc, VALUE *argv, VALUE self)
{
......@@ -225,12 +198,11 @@ ossl_x509extfactory_initialize(int argc, VALUE *argv, VALUE 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
* call-seq:
* ef.create_ext(ln_or_sn, "value", critical = false) -> X509::Extension
* ef.create_ext(ln_or_sn, "critical,value") -> X509::Extension
*
* Creates a new X509::Extension with passed values. See also x509v3_config(5).
*/
static VALUE
ossl_x509extfactory_create_ext(int argc, VALUE *argv, VALUE self)
......@@ -258,8 +230,11 @@ ossl_x509extfactory_create_ext(int argc, VALUE *argv, VALUE self)
GetX509ExtFactory(self, ctx);
obj = NewX509Ext(cX509Ext);
rconf = rb_iv_get(self, "@config");
conf = NIL_P(rconf) ? NULL : GetConfigPtr(rconf);
conf = NIL_P(rconf) ? NULL : DupConfigPtr(rconf);
X509V3_set_nconf(ctx, conf);
ext = X509V3_EXT_nconf_nid(conf, ctx, nid, RSTRING_PTR(valstr));
X509V3_set_ctx_nodb(ctx);
NCONF_free(conf);
if (!ext){
ossl_raise(eX509ExtError, "%"PRIsVALUE" = %"PRIsVALUE, oid, valstr);
}
......@@ -323,19 +298,40 @@ ossl_x509ext_initialize(int argc, VALUE *argv, VALUE self)
return self;
}
static VALUE
ossl_x509ext_initialize_copy(VALUE self, VALUE other)
{
X509_EXTENSION *ext, *ext_other, *ext_new;
rb_check_frozen(self);
GetX509Ext(self, ext);
SafeGetX509Ext(other, ext_other);
ext_new = X509_EXTENSION_dup(ext_other);
if (!ext_new)
ossl_raise(eX509ExtError, "X509_EXTENSION_dup");
SetX509Ext(self, ext_new);
X509_EXTENSION_free(ext);
return self;
}
static VALUE
ossl_x509ext_set_oid(VALUE self, VALUE oid)
{
X509_EXTENSION *ext;
ASN1_OBJECT *obj;
char *s;
s = StringValueCStr(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);
obj = OBJ_txt2obj(StringValueCStr(oid), 0);
if (!obj)
ossl_raise(eX509ExtError, "OBJ_txt2obj");
if (!X509_EXTENSION_set_object(ext, obj)) {
ASN1_OBJECT_free(obj);
ossl_raise(eX509ExtError, "X509_EXTENSION_set_object");
}
ASN1_OBJECT_free(obj);
return oid;
}
......@@ -346,17 +342,15 @@ ossl_x509ext_set_value(VALUE self, VALUE data)
X509_EXTENSION *ext;
ASN1_OCTET_STRING *asn1s;
GetX509Ext(self, ext);
data = ossl_to_der_if_possible(data);
StringValue(data);
if(!(asn1s = ASN1_OCTET_STRING_new())){
ossl_raise(eX509ExtError, NULL);
}
if(!ASN1_STRING_set((ASN1_STRING *)asn1s, (unsigned char *)RSTRING_PTR(data), RSTRING_LENINT(data))){
ASN1_OCTET_STRING_free(asn1s);
ossl_raise(eX509ExtError, NULL);
asn1s = X509_EXTENSION_get_data(ext);
if (!ASN1_OCTET_STRING_set(asn1s, (unsigned char *)RSTRING_PTR(data),
RSTRING_LENINT(data))) {
ossl_raise(eX509ExtError, "ASN1_OCTET_STRING_set");
}
GetX509Ext(self, ext);
X509_EXTENSION_set_data(ext, asn1s);
return data;
}
......@@ -447,6 +441,12 @@ ossl_x509ext_to_der(VALUE obj)
void
Init_ossl_x509ext(void)
{
#if 0
mOSSL = rb_define_module("OpenSSL");
eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
mX509 = rb_define_module_under(mOSSL, "X509");
#endif
eX509ExtError = rb_define_class_under(mX509, "ExtensionError", eOSSLError);
cX509ExtFactory = rb_define_class_under(mX509, "ExtensionFactory", rb_cObject);
......@@ -458,18 +458,18 @@ Init_ossl_x509ext(void)
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_attr(cX509ExtFactory, rb_intern("config"), 1, 1, 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_copy_func(cX509Ext, ossl_x509ext_initialize_copy);
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);
......
......@@ -181,6 +181,25 @@ ossl_x509name_initialize(int argc, VALUE *argv, VALUE self)
return self;
}
static VALUE
ossl_x509name_initialize_copy(VALUE self, VALUE other)
{
X509_NAME *name, *name_other, *name_new;
rb_check_frozen(self);
GetX509Name(self, name);
SafeGetX509Name(other, name_other);
name_new = X509_NAME_dup(name_other);
if (!name_new)
ossl_raise(eX509NameError, "X509_NAME_dup");
SetX509Name(self, name_new);
X509_NAME_free(name);
return self;
}
/*
* call-seq:
* name.add_entry(oid, value [, type]) => self
......@@ -307,10 +326,7 @@ ossl_x509name_to_a(VALUE self)
vname = rb_str_new2(short_name); /*do not free*/
}
value = X509_NAME_ENTRY_get_data(entry);
ary = rb_ary_new3(3,
vname,
rb_str_new((const char *)value->data, value->length),
INT2FIX(value->type));
ary = rb_ary_new3(3, vname, asn1str_to_str(value), INT2NUM(value->type));
rb_ary_push(ret, ary);
}
return ret;
......@@ -450,6 +466,12 @@ Init_ossl_x509name(void)
{
VALUE utf8str, ptrstr, ia5str, hash;
#if 0
mOSSL = rb_define_module("OpenSSL");
eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
mX509 = rb_define_module_under(mOSSL, "X509");
#endif
id_aref = rb_intern("[]");
eX509NameError = rb_define_class_under(mX509, "NameError", eOSSLError);
cX509Name = rb_define_class_under(mX509, "Name", rb_cObject);
......@@ -458,6 +480,7 @@ Init_ossl_x509name(void)
rb_define_alloc_func(cX509Name, ossl_x509name_alloc);
rb_define_method(cX509Name, "initialize", ossl_x509name_initialize, -1);
rb_define_copy_func(cX509Name, ossl_x509name_initialize_copy);
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);
......@@ -474,8 +497,7 @@ Init_ossl_x509name(void)
ptrstr = INT2NUM(V_ASN1_PRINTABLESTRING);
ia5str = INT2NUM(V_ASN1_IA5STRING);
/* Document-const: DEFAULT_OBJECT_TYPE
*
/*
* The default object type for name entries.
*/
rb_define_const(cX509Name, "DEFAULT_OBJECT_TYPE", utf8str);
......@@ -489,14 +511,12 @@ Init_ossl_x509name(void)
rb_hash_aset(hash, rb_str_new2("domainComponent"), ia5str);
rb_hash_aset(hash, rb_str_new2("emailAddress"), ia5str);
/* Document-const: OBJECT_TYPE_TEMPLATE
*
/*
* The default object type template for name entries.
*/
rb_define_const(cX509Name, "OBJECT_TYPE_TEMPLATE", hash);
/* Document-const: COMPAT
*
/*
* A flag for #to_s.
*
* Breaks the name returned into multiple lines if longer than 80
......@@ -504,24 +524,21 @@ Init_ossl_x509name(void)
*/
rb_define_const(cX509Name, "COMPAT", ULONG2NUM(XN_FLAG_COMPAT));
/* Document-const: RFC2253
*
/*
* A flag for #to_s.
*
* Returns an RFC2253 format name.
*/
rb_define_const(cX509Name, "RFC2253", ULONG2NUM(XN_FLAG_RFC2253));
/* Document-const: ONELINE
*
/*
* A flag for #to_s.
*
* Returns a more readable format than RFC2253.
*/
rb_define_const(cX509Name, "ONELINE", ULONG2NUM(XN_FLAG_ONELINE));
/* Document-const: MULTILINE
*
/*
* A flag for #to_s.
*
* Returns a multiline format.
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
......@@ -10,7 +10,7 @@ def crypt_by_password(alg, pass, salt, text)
puts
puts "--Encrypting--"
enc = OpenSSL::Cipher::Cipher.new(alg)
enc = OpenSSL::Cipher.new(alg)
enc.encrypt
enc.pkcs5_keyivgen(pass, salt)
cipher = enc.update(text)
......@@ -19,7 +19,7 @@ def crypt_by_password(alg, pass, salt, text)
puts
puts "--Decrypting--"
dec = OpenSSL::Cipher::Cipher.new(alg)
dec = OpenSSL::Cipher.new(alg)
dec.decrypt
dec.pkcs5_keyivgen(pass, salt)
plain = dec.update(cipher)
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册