Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 70 additions & 42 deletions ext/openssl/ossl.c
Original file line number Diff line number Diff line change
Expand Up @@ -388,10 +388,14 @@ osslerror_detailed_message(int argc, VALUE *argv, VALUE self)
* call-seq:
* OpenSSL.errors -> [String...]
*
* See any remaining errors held in queue.
* Returns any remaining errors held in the \OpenSSL thread-local error queue
* and clears the queue. This should normally return an empty array.
*
* Any errors you see here are probably due to a bug in Ruby's OpenSSL
* implementation.
* This is intended for debugging Ruby/OpenSSL. If you see any errors here,
* it likely indicates a bug in the extension. Please file an issue at
* https://github.com/ruby/openssl.
*
* For debugging your program, OpenSSL.debug= may be useful.
*/
static VALUE
ossl_get_errors(VALUE _)
Expand All @@ -415,6 +419,8 @@ VALUE dOSSL;
/*
* call-seq:
* OpenSSL.debug -> true | false
*
* Returns whether Ruby/OpenSSL's debug mode is currently enabled.
*/
static VALUE
ossl_debug_get(VALUE self)
Expand All @@ -424,9 +430,9 @@ ossl_debug_get(VALUE self)

/*
* call-seq:
* OpenSSL.debug = boolean -> boolean
* OpenSSL.debug = boolean
*
* Turns on or off debug mode. With debug mode, all errors added to the OpenSSL
* Turns on or off debug mode. With debug mode, all errors added to the \OpenSSL
* error queue will be printed to stderr.
*/
static VALUE
Expand All @@ -440,6 +446,8 @@ ossl_debug_set(VALUE self, VALUE val)
/*
* call-seq:
* OpenSSL.fips_mode -> true | false
*
* Returns whether the FIPS mode is currently enabled.
*/
static VALUE
ossl_fips_mode_get(VALUE self)
Expand All @@ -460,10 +468,10 @@ ossl_fips_mode_get(VALUE self)

/*
* call-seq:
* OpenSSL.fips_mode = boolean -> boolean
* OpenSSL.fips_mode = boolean
*
* Turns FIPS mode on or off. Turning on FIPS mode will obviously only have an
* effect for FIPS-capable installations of the OpenSSL library. Trying to do
* effect for FIPS-capable installations of the \OpenSSL library. Trying to do
* so otherwise will result in an error.
*
* === Examples
Expand Down Expand Up @@ -503,13 +511,13 @@ ossl_fips_mode_set(VALUE self, VALUE enabled)

/*
* call-seq:
* OpenSSL.fixed_length_secure_compare(string, string) -> boolean
* OpenSSL.fixed_length_secure_compare(string, string) -> true or false
*
* Constant time memory comparison for fixed length strings, such as results
* of HMAC calculations.
* of \HMAC calculations.
*
* Returns +true+ if the strings are identical, +false+ if they are of the same
* length but not identical. If the length is different, +ArgumentError+ is
* length but not identical. If the length is different, ArgumentError is
* raised.
*/
static VALUE
Expand All @@ -531,7 +539,7 @@ ossl_crypto_fixed_length_secure_compare(VALUE dummy, VALUE str1, VALUE str2)
}

/*
* OpenSSL provides SSL, TLS and general purpose cryptography. It wraps the
* OpenSSL provides \SSL, TLS and general purpose cryptography. It wraps the
* OpenSSL[https://www.openssl.org/] library.
*
* = Examples
Expand Down Expand Up @@ -586,7 +594,7 @@ ossl_crypto_fixed_length_secure_compare(VALUE dummy, VALUE str1, VALUE str2)
*
* === Loading an Encrypted Key
*
* OpenSSL will prompt you for your password when loading an encrypted key.
* \OpenSSL will prompt you for your password when loading an encrypted key.
* If you will not be able to type in the password you may provide it when
* loading the key:
*
Expand Down Expand Up @@ -649,7 +657,7 @@ ossl_crypto_fixed_length_secure_compare(VALUE dummy, VALUE str1, VALUE str2)
*
* == PBKDF2 Password-based Encryption
*
* If supported by the underlying OpenSSL version used, Password-based
* If supported by the underlying \OpenSSL version used, Password-based
* Encryption should use the features of PKCS5. If not supported or if
* required by legacy applications, the older, less secure methods specified
* in RFC 2898 are also supported (see below).
Expand Down Expand Up @@ -708,7 +716,7 @@ ossl_crypto_fixed_length_secure_compare(VALUE dummy, VALUE str1, VALUE str2)
* decrypted = cipher.update encrypted
* decrypted << cipher.final
*
* == X509 Certificates
* == \X509 Certificates
*
* === Creating a Certificate
*
Expand Down Expand Up @@ -745,7 +753,7 @@ ossl_crypto_fixed_length_secure_compare(VALUE dummy, VALUE str1, VALUE str2)
* extension_factory.create_extension('subjectKeyIdentifier', 'hash')
*
* The list of supported extensions (and in some cases their possible values)
* can be derived from the "objects.h" file in the OpenSSL source code.
* can be derived from the "objects.h" file in the \OpenSSL source code.
*
* === Signing a Certificate
*
Expand Down Expand Up @@ -899,23 +907,23 @@ ossl_crypto_fixed_length_secure_compare(VALUE dummy, VALUE str1, VALUE str2)
* io.write csr_cert.to_pem
* end
*
* == SSL and TLS Connections
* == \SSL and TLS Connections
*
* Using our created key and certificate we can create an SSL or TLS connection.
* An SSLContext is used to set up an SSL session.
* Using our created key and certificate we can create an \SSL or TLS
* connection. An OpenSSL::SSL::SSLContext is used to set up an \SSL session.
*
* context = OpenSSL::SSL::SSLContext.new
*
* === SSL Server
* === \SSL Server
*
* An SSL server requires the certificate and private key to communicate
* An \SSL server requires the certificate and private key to communicate
* securely with its clients:
*
* context.cert = cert
* context.key = key
*
* Then create an SSLServer with a TCP server socket and the context. Use the
* SSLServer like an ordinary TCP server.
* Then create an OpenSSL::SSL::SSLServer with a TCP server socket and the
* context. Use the SSLServer like an ordinary TCP server.
*
* require 'socket'
*
Expand All @@ -934,14 +942,15 @@ ossl_crypto_fixed_length_secure_compare(VALUE dummy, VALUE str1, VALUE str2)
* ssl_connection.close
* end
*
* === SSL client
* === \SSL client
*
* An SSL client is created with a TCP socket and the context.
* SSLSocket#connect must be called to initiate the SSL handshake and start
* encryption. A key and certificate are not required for the client socket.
* An \SSL client is created with a TCP socket and the context.
* OpenSSL::SSL::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.
* Note that OpenSSL::SSL::SSLSocket#close doesn't close the underlying socket
* by default. Set OpenSSL::SSL::SSLSocket#sync_close to true if you want.
*
* require 'socket'
*
Expand All @@ -957,7 +966,7 @@ ossl_crypto_fixed_length_secure_compare(VALUE dummy, VALUE str1, VALUE str2)
*
* === Peer Verification
*
* An unverified SSL connection does not provide much security. For enhanced
* An unverified \SSL connection does not provide much security. For enhanced
* security the client or server can verify the certificate of its peer.
*
* The client can be modified to verify the server's certificate against the
Expand Down Expand Up @@ -1008,40 +1017,59 @@ Init_openssl(void)
rb_define_singleton_method(mOSSL, "fixed_length_secure_compare", ossl_crypto_fixed_length_secure_compare, 2);

/*
* Version of OpenSSL the ruby OpenSSL extension was built with
* \OpenSSL library version string used to compile the Ruby/OpenSSL
* extension. This may differ from the version used at runtime.
*/
rb_define_const(mOSSL, "OPENSSL_VERSION", rb_str_new2(OPENSSL_VERSION_TEXT));
rb_define_const(mOSSL, "OPENSSL_VERSION",
rb_obj_freeze(rb_str_new_cstr(OPENSSL_VERSION_TEXT)));

/*
* Version of OpenSSL the ruby OpenSSL extension is running with
* \OpenSSL library version string currently used at runtime.
*/
rb_define_const(mOSSL, "OPENSSL_LIBRARY_VERSION", rb_str_new2(OpenSSL_version(OPENSSL_VERSION)));
rb_define_const(
mOSSL,
"OPENSSL_LIBRARY_VERSION",
rb_obj_freeze(rb_str_new_cstr(OpenSSL_version(OPENSSL_VERSION)))
);

/*
* Version number of OpenSSL the ruby OpenSSL extension was built with
* (base 16). The formats are below.
* \OpenSSL library version number used to compile the Ruby/OpenSSL
* extension. This may differ from the version used at runtime.
*
* [OpenSSL 3] <tt>0xMNN00PP0 (major minor 00 patch 0)</tt>
* [OpenSSL before 3] <tt>0xMNNFFPPS (major minor fix patch status)</tt>
* [LibreSSL] <tt>0x20000000 (fixed value)</tt>
* The version number is encoded into a single integer value. The number
* follows the format:
*
* [\OpenSSL 3.0.0 or later]
* <tt>0xMNN00PP0</tt> (major minor 00 patch 0)
* [\OpenSSL 1.1.1 or earlier]
* <tt>0xMNNFFPPS</tt> (major minor fix patch status)
* [LibreSSL]
* <tt>0x20000000</tt> (a fixed value)
*
* See also the man page OPENSSL_VERSION_NUMBER(3).
*/
rb_define_const(mOSSL, "OPENSSL_VERSION_NUMBER", INT2NUM(OPENSSL_VERSION_NUMBER));

#if defined(LIBRESSL_VERSION_NUMBER)
/*
* Version number of LibreSSL the ruby OpenSSL extension was built with
* (base 16). The format is <tt>0xMNNFF00f (major minor fix 00
* status)</tt>. This constant is only defined in LibreSSL cases.
* LibreSSL library version number used to compile the Ruby/OpenSSL
* extension. This may differ from the version used at runtime.
*
* This constant is only defined if the extension was compiled against
* LibreSSL. The number follows the format:
* <tt>0xMNNFF00f</tt> (major minor fix 00 status).
*
* See also the man page LIBRESSL_VERSION_NUMBER(3).
*/
rb_define_const(mOSSL, "LIBRESSL_VERSION_NUMBER", INT2NUM(LIBRESSL_VERSION_NUMBER));
#endif

/*
* Boolean indicating whether OpenSSL is FIPS-capable or not
* Boolean indicating whether the \OpenSSL library is FIPS-capable or not.
* Always <tt>true</tt> for \OpenSSL 3.0 and later.
*
* This is obsolete and will be removed in the future.
* See also OpenSSL.fips_mode.
*/
rb_define_const(mOSSL, "OPENSSL_FIPS",
/* OpenSSL 3 is FIPS-capable even when it is installed without fips option */
Expand Down
18 changes: 10 additions & 8 deletions ext/openssl/ossl_asn1.c
Original file line number Diff line number Diff line change
Expand Up @@ -1397,8 +1397,6 @@ void
Init_ossl_asn1(void)
{
#undef rb_intern
VALUE ary;
int i;

sym_UNIVERSAL = ID2SYM(rb_intern_const("UNIVERSAL"));
sym_CONTEXT_SPECIFIC = ID2SYM(rb_intern_const("CONTEXT_SPECIFIC"));
Expand Down Expand Up @@ -1548,17 +1546,20 @@ Init_ossl_asn1(void)
rb_define_module_function(mASN1, "traverse", ossl_asn1_traverse, 1);
rb_define_module_function(mASN1, "decode", ossl_asn1_decode, 1);
rb_define_module_function(mASN1, "decode_all", ossl_asn1_decode_all, 1);
ary = rb_ary_new();

VALUE ary = rb_ary_new_capa(ossl_asn1_info_size);
for (int i = 0; i < ossl_asn1_info_size; i++) {
const char *name = ossl_asn1_info[i].name;
if (name[0] == '[')
continue;
rb_define_const(mASN1, name, INT2NUM(i));
rb_ary_store(ary, i, rb_obj_freeze(rb_str_new_cstr(name)));
}
rb_obj_freeze(ary);
/*
* Array storing tag names at the tag's index.
*/
rb_define_const(mASN1, "UNIVERSAL_TAG_NAME", ary);
for(i = 0; i < ossl_asn1_info_size; i++){
if(ossl_asn1_info[i].name[0] == '[') continue;
rb_define_const(mASN1, ossl_asn1_info[i].name, INT2NUM(i));
rb_ary_store(ary, i, rb_str_new2(ossl_asn1_info[i].name));
}

/* Document-class: OpenSSL::ASN1::ASN1Data
*
Expand Down Expand Up @@ -1880,6 +1881,7 @@ do{\
rb_hash_aset(class_tag_map, cASN1GeneralString, INT2NUM(V_ASN1_GENERALSTRING));
rb_hash_aset(class_tag_map, cASN1UniversalString, INT2NUM(V_ASN1_UNIVERSALSTRING));
rb_hash_aset(class_tag_map, cASN1BMPString, INT2NUM(V_ASN1_BMPSTRING));
rb_obj_freeze(class_tag_map);

id_each = rb_intern_const("each");
}
3 changes: 2 additions & 1 deletion ext/openssl/ossl_x509.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ VALUE mX509;

#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()))
rb_define_const(mX509, "DEFAULT_" #x, \
rb_obj_freeze(rb_str_new_cstr(X509_get_default_##i())))

ASN1_TIME *
ossl_x509_time_adjust(ASN1_TIME *s, VALUE time)
Expand Down
1 change: 1 addition & 0 deletions ext/openssl/ossl_x509name.c
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,7 @@ Init_ossl_x509name(void)
rb_hash_aset(hash, rb_str_new2("DC"), ia5str);
rb_hash_aset(hash, rb_str_new2("domainComponent"), ia5str);
rb_hash_aset(hash, rb_str_new2("emailAddress"), ia5str);
rb_obj_freeze(hash);

/*
* The default object type template for name entries.
Expand Down
8 changes: 6 additions & 2 deletions lib/openssl.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,16 @@
require_relative 'openssl/x509'

module OpenSSL
# call-seq:
# OpenSSL.secure_compare(string, string) -> boolean
# :call-seq:
# OpenSSL.secure_compare(string, string) -> true or false
#
# Constant time memory comparison. Inputs are hashed using SHA-256 to mask
# the length of the secret. Returns +true+ if the strings are identical,
# +false+ otherwise.
#
# This method is expensive due to the SHA-256 hashing. In most cases, where
# the input lengths are known to be equal or are not sensitive,
# OpenSSL.fixed_length_secure_compare should be used instead.
def self.secure_compare(a, b)
hashed_a = OpenSSL::Digest.digest('SHA256', a)
hashed_b = OpenSSL::Digest.digest('SHA256', b)
Expand Down
2 changes: 1 addition & 1 deletion lib/openssl/digest.rb
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ class Digest < Digest; end # :nodoc:
# OpenSSL::Digest("MD5")
# # => OpenSSL::Digest::MD5
#
# Digest("Foo")
# OpenSSL::Digest("Foo")
# # => NameError: wrong constant name Foo

def Digest(name)
Expand Down
1 change: 1 addition & 0 deletions lib/openssl/version.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# frozen_string_literal: true

module OpenSSL
# The version string of Ruby/OpenSSL.
VERSION = "4.0.0.pre"
end