mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
import OpenSSL from trunk
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8@12496 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
f5be4ddc8d
commit
18342ff8e0
48 changed files with 3828 additions and 365 deletions
20
NEWS
20
NEWS
|
@ -7,6 +7,26 @@ Note that each entry is kept so brief that no reason behind or
|
|||
reference information is supplied with. For a full list of changes
|
||||
with all sufficient information, see the ChangeLog file.
|
||||
|
||||
== Changes with Ruby 1.8.6
|
||||
|
||||
=== Library updates (outstanding ones only)
|
||||
|
||||
* openssl
|
||||
|
||||
* New classes:
|
||||
OpenSSL::PKey::EC
|
||||
OpenSSL::PKey::EC::Group
|
||||
OpenSSL::PKey::EC::Point
|
||||
OpenSSL::PKey::PKCS5
|
||||
OpenSSL::SSL::Session
|
||||
|
||||
* Documentation!
|
||||
|
||||
* Various new methods (see documentation).
|
||||
|
||||
* Remove redundant module namespace in Cipher, Digest, PKCS7, PKCS12.
|
||||
Compatibility classes are provided which will be removed in Ruby 1.9.
|
||||
|
||||
== Changes with Ruby 1.8.5
|
||||
|
||||
=== New platforms/build tools support
|
||||
|
|
|
@ -59,6 +59,8 @@ unless have_header("openssl/conf_api.h")
|
|||
exit 1
|
||||
end
|
||||
|
||||
%w"rb_str_set_len rb_block_call".each {|func| have_func(func, "ruby.h")}
|
||||
|
||||
message "=== Checking for OpenSSL features... ===\n"
|
||||
have_func("ERR_peek_last_error")
|
||||
have_func("BN_mod_add")
|
||||
|
@ -81,6 +83,8 @@ have_func("HMAC_CTX_cleanup")
|
|||
have_func("HMAC_CTX_copy")
|
||||
have_func("HMAC_CTX_init")
|
||||
have_func("PEM_def_callback")
|
||||
have_func("PKCS5_PBKDF2_HMAC")
|
||||
have_func("PKCS5_PBKDF2_HMAC_SHA1")
|
||||
have_func("X509V3_set_nconf")
|
||||
have_func("X509V3_EXT_nconf_nid")
|
||||
have_func("X509_CRL_add0_revoked")
|
||||
|
|
|
@ -19,6 +19,7 @@ require 'openssl.so'
|
|||
require 'openssl/bn'
|
||||
require 'openssl/cipher'
|
||||
require 'openssl/digest'
|
||||
require 'openssl/pkcs7'
|
||||
require 'openssl/ssl'
|
||||
require 'openssl/x509'
|
||||
|
||||
|
|
|
@ -57,10 +57,10 @@ module Buffering
|
|||
if size == 0
|
||||
if buf
|
||||
buf.clear
|
||||
return buf
|
||||
else
|
||||
buf = ""
|
||||
return ""
|
||||
end
|
||||
return @eof ? nil : buf
|
||||
end
|
||||
until @eof
|
||||
break if size && size <= @rbuffer.size
|
||||
|
@ -78,10 +78,10 @@ module Buffering
|
|||
if maxlen == 0
|
||||
if buf
|
||||
buf.clear
|
||||
return buf
|
||||
else
|
||||
buf = ""
|
||||
return ""
|
||||
end
|
||||
return @eof ? nil : buf
|
||||
end
|
||||
if @rbuffer.empty?
|
||||
begin
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
#require 'openssl'
|
||||
|
||||
module OpenSSL
|
||||
module Cipher
|
||||
class Cipher
|
||||
%w(AES CAST5 BF DES IDEA RC2 RC4 RC5).each{|name|
|
||||
klass = Class.new(Cipher){
|
||||
define_method(:initialize){|*args|
|
||||
|
@ -41,18 +41,25 @@ module OpenSSL
|
|||
const_set("AES#{keylen}", klass)
|
||||
}
|
||||
|
||||
class Cipher
|
||||
# Generate, set, and return a random key.
|
||||
# You must call cipher.encrypt or cipher.decrypt before calling this method.
|
||||
def random_key
|
||||
str = OpenSSL::Random.random_bytes(self.key_len)
|
||||
self.key = str
|
||||
return str
|
||||
end
|
||||
|
||||
# Generate, set, and return a random iv.
|
||||
# You must call cipher.encrypt or cipher.decrypt before calling this method.
|
||||
def random_iv
|
||||
str = OpenSSL::Random.random_bytes(self.iv_len)
|
||||
self.iv = str
|
||||
return str
|
||||
end
|
||||
|
||||
# This class is only provided for backwards compatibility. Use OpenSSL::Digest in the future.
|
||||
class Cipher < Cipher
|
||||
# add warning
|
||||
end
|
||||
end # Cipher
|
||||
end # OpenSSL
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
#require 'openssl'
|
||||
|
||||
module OpenSSL
|
||||
module Digest
|
||||
class Digest
|
||||
|
||||
alg = %w(DSS DSS1 MD2 MD4 MD5 MDC2 RIPEMD160 SHA SHA1)
|
||||
if OPENSSL_VERSION_NUMBER > 0x00908000
|
||||
|
@ -44,6 +44,11 @@ module OpenSSL
|
|||
const_set(name, klass)
|
||||
}
|
||||
|
||||
# This class is only provided for backwards compatibility. Use OpenSSL::Digest in the future.
|
||||
class Digest < Digest
|
||||
# add warning
|
||||
end
|
||||
|
||||
end # Digest
|
||||
end # OpenSSL
|
||||
|
||||
|
|
25
ext/openssl/lib/openssl/pkcs7.rb
Normal file
25
ext/openssl/lib/openssl/pkcs7.rb
Normal file
|
@ -0,0 +1,25 @@
|
|||
=begin
|
||||
= $RCSfile$ -- PKCS7
|
||||
|
||||
= Licence
|
||||
This program is licenced under the same licence as Ruby.
|
||||
(See the file 'LICENCE'.)
|
||||
|
||||
= Version
|
||||
$Id: digest.rb 12148 2007-04-05 05:59:22Z technorama $
|
||||
=end
|
||||
|
||||
module OpenSSL
|
||||
class PKCS7
|
||||
# This class is only provided for backwards compatibility. Use OpenSSL::PKCS7 in the future.
|
||||
class PKCS7 < PKCS7
|
||||
def initialize(*args)
|
||||
super(*args)
|
||||
|
||||
warn("Warning: OpenSSL::PKCS7::PKCS7 is deprecated after Ruby 1.9; use OpenSSL::PKCS7 instead")
|
||||
end
|
||||
end
|
||||
|
||||
end # PKCS7
|
||||
end # OpenSSL
|
||||
|
|
@ -90,6 +90,12 @@ module OpenSSL
|
|||
end
|
||||
raise SSLError, "hostname not match"
|
||||
end
|
||||
|
||||
def session
|
||||
SSL::Session.new(self)
|
||||
rescue SSL::Session::SessionError
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
class SSLServer
|
||||
|
|
|
@ -59,7 +59,7 @@ ossl_x509_ary2sk0(VALUE ary)
|
|||
sk = sk_X509_new_null();
|
||||
if (!sk) ossl_raise(eOSSLError, NULL);
|
||||
|
||||
for (i = 0; i < RARRAY(ary)->len; i++) {
|
||||
for (i = 0; i < RARRAY_LEN(ary); i++) {
|
||||
val = rb_ary_entry(ary, i);
|
||||
if (!rb_obj_is_kind_of(val, cX509Cert)) {
|
||||
sk_X509_pop_free(sk, X509_free);
|
||||
|
@ -131,7 +131,7 @@ ossl_buf2str(char *buf, int len)
|
|||
int status = 0;
|
||||
|
||||
str = rb_protect((VALUE(*)_((VALUE)))ossl_str_new, len, &status);
|
||||
if(!NIL_P(str)) memcpy(RSTRING(str)->ptr, buf, len);
|
||||
if(!NIL_P(str)) memcpy(RSTRING_PTR(str), buf, len);
|
||||
OPENSSL_free(buf);
|
||||
if(status) rb_jump_tag(status);
|
||||
|
||||
|
@ -170,7 +170,7 @@ ossl_pem_passwd_cb(char *buf, int max_len, int flag, void *pwd)
|
|||
rflag = flag ? Qtrue : Qfalse;
|
||||
pass = rb_protect(ossl_pem_passwd_cb0, rflag, &status);
|
||||
if (status) return -1; /* exception was raised. */
|
||||
len = RSTRING(pass)->len;
|
||||
len = RSTRING_LEN(pass);
|
||||
if (len < 4) { /* 4 is OpenSSL hardcoded limit */
|
||||
rb_warning("password must be longer than 4 bytes");
|
||||
continue;
|
||||
|
@ -179,7 +179,7 @@ ossl_pem_passwd_cb(char *buf, int max_len, int flag, void *pwd)
|
|||
rb_warning("password must be shorter then %d bytes", max_len-1);
|
||||
continue;
|
||||
}
|
||||
memcpy(buf, RSTRING(pass)->ptr, len);
|
||||
memcpy(buf, RSTRING_PTR(pass), len);
|
||||
break;
|
||||
}
|
||||
return len;
|
||||
|
@ -310,6 +310,14 @@ ossl_raise(VALUE exc, const char *fmt, ...)
|
|||
rb_exc_raise(rb_exc_new(exc, buf, len));
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* OpenSSL.errors -> [String...]
|
||||
*
|
||||
* See any remaining errors held in queue.
|
||||
*
|
||||
* Any errors you see here are probably due to a bug in ruby's OpenSSL implementation.
|
||||
*/
|
||||
VALUE
|
||||
ossl_get_errors()
|
||||
{
|
||||
|
@ -345,12 +353,23 @@ ossl_debug(const char *fmt, ...)
|
|||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* OpenSSL.debug -> true | false
|
||||
*/
|
||||
static VALUE
|
||||
ossl_debug_get(VALUE self)
|
||||
{
|
||||
return dOSSL;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* OpenSSL.debug = boolean -> boolean
|
||||
*
|
||||
* Turns on or off CRYPTO_MEM_CHECK.
|
||||
* Also shows some debugging message on stderr.
|
||||
*/
|
||||
static VALUE
|
||||
ossl_debug_set(VALUE self, VALUE val)
|
||||
{
|
||||
|
@ -427,8 +446,8 @@ Init_openssl()
|
|||
/*
|
||||
* Verify callback Proc index for ext-data
|
||||
*/
|
||||
ossl_verify_cb_idx =
|
||||
X509_STORE_CTX_get_ex_new_index(0, "ossl_verify_cb_idx", 0, 0, 0);
|
||||
if ((ossl_verify_cb_idx = X509_STORE_CTX_get_ex_new_index(0, "ossl_verify_cb_idx", 0, 0, 0)) < 0)
|
||||
ossl_raise(eOSSLError, "X509_STORE_CTX_get_ex_new_index");
|
||||
|
||||
/*
|
||||
* Init debug core
|
||||
|
@ -454,6 +473,7 @@ Init_openssl()
|
|||
Init_ossl_ns_spki();
|
||||
Init_ossl_pkcs12();
|
||||
Init_ossl_pkcs7();
|
||||
Init_ossl_pkcs5();
|
||||
Init_ossl_pkey();
|
||||
Init_ossl_rand();
|
||||
Init_ossl_ssl();
|
||||
|
|
|
@ -17,6 +17,11 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
mOSSL = rb_define_module("OpenSSL");
|
||||
mX509 = rb_define_module_under(mOSSL, "X509");
|
||||
#endif
|
||||
|
||||
/*
|
||||
* OpenSSL has defined RFILE and Ruby has defined RFILE - so undef it!
|
||||
*/
|
||||
|
@ -40,8 +45,8 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
#if defined(_WIN32)
|
||||
# define OpenFile WINAPI_OpenFile
|
||||
# define OSSL_NO_CONF_API 1
|
||||
# include <winsock2.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
#include <openssl/err.h>
|
||||
|
@ -64,9 +69,6 @@ extern "C" {
|
|||
# define OSSL_OCSP_ENABLED
|
||||
# include <openssl/ocsp.h>
|
||||
#endif
|
||||
#if defined(_WIN32)
|
||||
# undef OpenFile
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Common Module
|
||||
|
@ -117,11 +119,10 @@ VALUE ossl_x509crl_sk2ary(STACK_OF(X509_CRL) *crl);
|
|||
VALUE ossl_buf2str(char *buf, int len);
|
||||
#define ossl_str_adjust(str, p) \
|
||||
do{\
|
||||
int len = RSTRING(str)->len;\
|
||||
int newlen = (p) - (unsigned char*)RSTRING(str)->ptr;\
|
||||
int len = RSTRING_LEN(str);\
|
||||
int newlen = (p) - (unsigned char*)RSTRING_PTR(str);\
|
||||
assert(newlen <= len);\
|
||||
RSTRING(str)->len = newlen;\
|
||||
RSTRING(str)->ptr[newlen] = 0;\
|
||||
rb_str_set_len(str, newlen);\
|
||||
}while(0)
|
||||
|
||||
/*
|
||||
|
|
|
@ -214,7 +214,7 @@ obj_to_asn1bstr(VALUE obj, long unused_bits)
|
|||
StringValue(obj);
|
||||
if(!(bstr = ASN1_BIT_STRING_new()))
|
||||
ossl_raise(eASN1Error, NULL);
|
||||
ASN1_BIT_STRING_set(bstr, RSTRING(obj)->ptr, RSTRING(obj)->len);
|
||||
ASN1_BIT_STRING_set(bstr, RSTRING_PTR(obj), RSTRING_LEN(obj));
|
||||
bstr->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07); /* clear */
|
||||
bstr->flags |= ASN1_STRING_FLAG_BITS_LEFT|(unused_bits&0x07);
|
||||
|
||||
|
@ -229,7 +229,7 @@ obj_to_asn1str(VALUE obj)
|
|||
StringValue(obj);
|
||||
if(!(str = ASN1_STRING_new()))
|
||||
ossl_raise(eASN1Error, NULL);
|
||||
ASN1_STRING_set(str, RSTRING(obj)->ptr, RSTRING(obj)->len);
|
||||
ASN1_STRING_set(str, RSTRING_PTR(obj), RSTRING_LEN(obj));
|
||||
|
||||
return str;
|
||||
}
|
||||
|
@ -253,8 +253,8 @@ obj_to_asn1obj(VALUE obj)
|
|||
ASN1_OBJECT *a1obj;
|
||||
|
||||
StringValue(obj);
|
||||
a1obj = OBJ_txt2obj(RSTRING(obj)->ptr, 0);
|
||||
if(!a1obj) a1obj = OBJ_txt2obj(RSTRING(obj)->ptr, 1);
|
||||
a1obj = OBJ_txt2obj(RSTRING_PTR(obj), 0);
|
||||
if(!a1obj) a1obj = OBJ_txt2obj(RSTRING_PTR(obj), 1);
|
||||
if(!a1obj) ossl_raise(eASN1Error, "invalid OBJECT ID");
|
||||
|
||||
return a1obj;
|
||||
|
@ -295,7 +295,7 @@ obj_to_asn1derstr(VALUE obj)
|
|||
str = ossl_to_der(obj);
|
||||
if(!(a1str = ASN1_STRING_new()))
|
||||
ossl_raise(eASN1Error, NULL);
|
||||
ASN1_STRING_set(a1str, RSTRING(str)->ptr, RSTRING(str)->len);
|
||||
ASN1_STRING_set(a1str, RSTRING_PTR(str), RSTRING_LEN(str));
|
||||
|
||||
return a1str;
|
||||
}
|
||||
|
@ -445,7 +445,7 @@ decode_time(unsigned char* der, int length)
|
|||
/********/
|
||||
|
||||
typedef struct {
|
||||
char *name;
|
||||
const char *name;
|
||||
VALUE *klass;
|
||||
} ossl_asn1_info_t;
|
||||
|
||||
|
@ -678,7 +678,7 @@ static VALUE
|
|||
join_der(VALUE enumerable)
|
||||
{
|
||||
VALUE str = rb_str_new(0, 0);
|
||||
rb_iterate(rb_each, enumerable, join_der_i, str);
|
||||
rb_block_call(enumerable, rb_intern("each"), 0, 0, join_der_i, str);
|
||||
return str;
|
||||
}
|
||||
|
||||
|
@ -699,13 +699,13 @@ ossl_asn1data_to_der(VALUE self)
|
|||
|
||||
tag = ossl_asn1_tag(self);
|
||||
tag_class = ossl_asn1_tag_class(self);
|
||||
if((length = ASN1_object_size(1, RSTRING(value)->len, tag)) <= 0)
|
||||
if((length = ASN1_object_size(1, RSTRING_LEN(value), tag)) <= 0)
|
||||
ossl_raise(eASN1Error, NULL);
|
||||
der = rb_str_new(0, length);
|
||||
p = RSTRING(der)->ptr;
|
||||
ASN1_put_object(&p, is_cons, RSTRING(value)->len, tag, tag_class);
|
||||
memcpy(p, RSTRING(value)->ptr, RSTRING(value)->len);
|
||||
p += RSTRING(value)->len;
|
||||
p = RSTRING_PTR(der);
|
||||
ASN1_put_object(&p, is_cons, RSTRING_LEN(value), tag, tag_class);
|
||||
memcpy(p, RSTRING_PTR(value), RSTRING_LEN(value));
|
||||
p += RSTRING_LEN(value);
|
||||
ossl_str_adjust(der, p);
|
||||
|
||||
return der;
|
||||
|
@ -824,8 +824,8 @@ ossl_asn1_traverse(VALUE self, VALUE obj)
|
|||
|
||||
obj = ossl_to_der_if_possible(obj);
|
||||
tmp = rb_str_new4(StringValue(obj));
|
||||
p = RSTRING(tmp)->ptr;
|
||||
ossl_asn1_decode0(&p, RSTRING(tmp)->len, &offset, 0, 0, 1);
|
||||
p = RSTRING_PTR(tmp);
|
||||
ossl_asn1_decode0(&p, RSTRING_LEN(tmp), &offset, 0, 0, 1);
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
@ -840,8 +840,8 @@ ossl_asn1_decode(VALUE self, VALUE obj)
|
|||
|
||||
obj = ossl_to_der_if_possible(obj);
|
||||
tmp = rb_str_new4(StringValue(obj));
|
||||
p = RSTRING(tmp)->ptr;
|
||||
ary = ossl_asn1_decode0(&p, RSTRING(tmp)->len, &offset, 0, 1, 0);
|
||||
p = RSTRING_PTR(tmp);
|
||||
ary = ossl_asn1_decode0(&p, RSTRING_LEN(tmp), &offset, 0, 1, 0);
|
||||
ret = rb_ary_entry(ary, 0);
|
||||
|
||||
return ret;
|
||||
|
@ -857,8 +857,8 @@ ossl_asn1_decode_all(VALUE self, VALUE obj)
|
|||
|
||||
obj = ossl_to_der_if_possible(obj);
|
||||
tmp = rb_str_new4(StringValue(obj));
|
||||
p = RSTRING(tmp)->ptr;
|
||||
ret = ossl_asn1_decode0(&p, RSTRING(tmp)->len, &offset, 0, 0, 0);
|
||||
p = RSTRING_PTR(tmp);
|
||||
ret = ossl_asn1_decode0(&p, RSTRING_LEN(tmp), &offset, 0, 0, 0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -973,21 +973,21 @@ ossl_asn1cons_to_der(VALUE self)
|
|||
explicit = ossl_asn1_is_explicit(self);
|
||||
value = join_der(ossl_asn1_get_value(self));
|
||||
|
||||
seq_len = ASN1_object_size(1, RSTRING(value)->len, tag);
|
||||
seq_len = ASN1_object_size(1, RSTRING_LEN(value), tag);
|
||||
length = ASN1_object_size(1, seq_len, tn);
|
||||
str = rb_str_new(0, length);
|
||||
p = RSTRING(str)->ptr;
|
||||
p = RSTRING_PTR(str);
|
||||
if(tc == V_ASN1_UNIVERSAL)
|
||||
ASN1_put_object(&p, 1, RSTRING(value)->len, tn, tc);
|
||||
ASN1_put_object(&p, 1, RSTRING_LEN(value), tn, tc);
|
||||
else{
|
||||
if(explicit){
|
||||
ASN1_put_object(&p, 1, seq_len, tn, tc);
|
||||
ASN1_put_object(&p, 1, RSTRING(value)->len, tag, V_ASN1_UNIVERSAL);
|
||||
ASN1_put_object(&p, 1, RSTRING_LEN(value), tag, V_ASN1_UNIVERSAL);
|
||||
}
|
||||
else ASN1_put_object(&p, 1, RSTRING(value)->len, tn, tc);
|
||||
else ASN1_put_object(&p, 1, RSTRING_LEN(value), tn, tc);
|
||||
}
|
||||
memcpy(p, RSTRING(value)->ptr, RSTRING(value)->len);
|
||||
p += RSTRING(value)->len;
|
||||
memcpy(p, RSTRING_PTR(value), RSTRING_LEN(value));
|
||||
p += RSTRING_LEN(value);
|
||||
ossl_str_adjust(str, p);
|
||||
|
||||
return str;
|
||||
|
@ -1007,7 +1007,7 @@ ossl_asn1obj_s_register(VALUE self, VALUE oid, VALUE sn, VALUE ln)
|
|||
StringValue(sn);
|
||||
StringValue(ln);
|
||||
|
||||
if(!OBJ_create(RSTRING(oid)->ptr, RSTRING(sn)->ptr, RSTRING(ln)->ptr))
|
||||
if(!OBJ_create(RSTRING_PTR(oid), RSTRING_PTR(sn), RSTRING_PTR(ln)))
|
||||
ossl_raise(eASN1Error, NULL);
|
||||
|
||||
return Qtrue;
|
||||
|
@ -1112,9 +1112,9 @@ Init_ossl_asn1()
|
|||
}
|
||||
|
||||
cASN1Data = rb_define_class_under(mASN1, "ASN1Data", rb_cObject);
|
||||
rb_attr(cASN1Data, rb_intern("value"), 1, 1, Qtrue);
|
||||
rb_attr(cASN1Data, rb_intern("tag"), 1, 1, Qtrue);
|
||||
rb_attr(cASN1Data, rb_intern("tag_class"), 1, 1, Qtrue);
|
||||
rb_attr(cASN1Data, rb_intern("value"), 1, 1, 0);
|
||||
rb_attr(cASN1Data, rb_intern("tag"), 1, 1, 0);
|
||||
rb_attr(cASN1Data, rb_intern("tag_class"), 1, 1, 0);
|
||||
rb_define_method(cASN1Data, "initialize", ossl_asn1data_initialize, 3);
|
||||
rb_define_method(cASN1Data, "to_der", ossl_asn1data_to_der, 0);
|
||||
|
||||
|
@ -1166,5 +1166,5 @@ do{\
|
|||
rb_define_method(cASN1ObjectId, "oid", ossl_asn1obj_get_oid, 0);
|
||||
rb_define_alias(cASN1ObjectId, "short_name", "sn");
|
||||
rb_define_alias(cASN1ObjectId, "long_name", "ln");
|
||||
rb_attr(cASN1BitString, rb_intern("unused_bits"), 1, 1, Qtrue);
|
||||
rb_attr(cASN1BitString, rb_intern("unused_bits"), 1, 1, 0);
|
||||
}
|
||||
|
|
|
@ -19,16 +19,29 @@ ossl_obj2bio(VALUE obj)
|
|||
BIO *bio;
|
||||
|
||||
if (TYPE(obj) == T_FILE) {
|
||||
OpenFile *fptr;
|
||||
rb_io_t *fptr;
|
||||
FILE *fp;
|
||||
int fd;
|
||||
|
||||
GetOpenFile(obj, fptr);
|
||||
rb_io_check_readable(fptr);
|
||||
bio = BIO_new_fp(fptr->f, BIO_NOCLOSE);
|
||||
if ((fd = dup(FPTR_TO_FD(fptr))) < 0){
|
||||
rb_sys_fail(0);
|
||||
}
|
||||
if (!(fp = fdopen(fd, "r"))){
|
||||
close(fd);
|
||||
rb_sys_fail(0);
|
||||
}
|
||||
if (!(bio = BIO_new_fp(fp, BIO_CLOSE))){
|
||||
fclose(fp);
|
||||
ossl_raise(eOSSLError, NULL);
|
||||
}
|
||||
}
|
||||
else {
|
||||
StringValue(obj);
|
||||
bio = BIO_new_mem_buf(RSTRING(obj)->ptr, RSTRING(obj)->len);
|
||||
}
|
||||
bio = BIO_new_mem_buf(RSTRING_PTR(obj), RSTRING_LEN(obj));
|
||||
if (!bio) ossl_raise(eOSSLError, NULL);
|
||||
}
|
||||
|
||||
return bio;
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ VALUE eBNError;
|
|||
* Public
|
||||
*/
|
||||
VALUE
|
||||
ossl_bn_new(BIGNUM *bn)
|
||||
ossl_bn_new(const BIGNUM *bn)
|
||||
{
|
||||
BIGNUM *newbn;
|
||||
VALUE obj;
|
||||
|
@ -100,6 +100,13 @@ ossl_bn_alloc(VALUE klass)
|
|||
return obj;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* BN.new => aBN
|
||||
* BN.new(bn) => aBN
|
||||
* BN.new(string) => aBN
|
||||
* BN.new(string, 0 | 2 | 10 | 16) => aBN
|
||||
*/
|
||||
static VALUE
|
||||
ossl_bn_initialize(int argc, VALUE *argv, VALUE self)
|
||||
{
|
||||
|
@ -124,22 +131,22 @@ ossl_bn_initialize(int argc, VALUE *argv, VALUE self)
|
|||
|
||||
switch (base) {
|
||||
case 0:
|
||||
if (!BN_mpi2bn(RSTRING(str)->ptr, RSTRING(str)->len, bn)) {
|
||||
if (!BN_mpi2bn(RSTRING_PTR(str), RSTRING_LEN(str), bn)) {
|
||||
ossl_raise(eBNError, NULL);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (!BN_bin2bn(RSTRING(str)->ptr, RSTRING(str)->len, bn)) {
|
||||
if (!BN_bin2bn(RSTRING_PTR(str), RSTRING_LEN(str), bn)) {
|
||||
ossl_raise(eBNError, NULL);
|
||||
}
|
||||
break;
|
||||
case 10:
|
||||
if (!BN_dec2bn(&bn, RSTRING(str)->ptr)) {
|
||||
if (!BN_dec2bn(&bn, RSTRING_PTR(str))) {
|
||||
ossl_raise(eBNError, NULL);
|
||||
}
|
||||
break;
|
||||
case 16:
|
||||
if (!BN_hex2bn(&bn, RSTRING(str)->ptr)) {
|
||||
if (!BN_hex2bn(&bn, RSTRING_PTR(str))) {
|
||||
ossl_raise(eBNError, NULL);
|
||||
}
|
||||
break;
|
||||
|
@ -149,6 +156,19 @@ ossl_bn_initialize(int argc, VALUE *argv, VALUE self)
|
|||
return self;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* bn.to_s => string
|
||||
* bn.to_s(base) => string
|
||||
*
|
||||
* === Parameters
|
||||
* * +base+ - integer
|
||||
* * * Valid values:
|
||||
* * * * 0 - MPI
|
||||
* * * * 2 - binary
|
||||
* * * * 10 - the default
|
||||
* * * * 16 - hex
|
||||
*/
|
||||
static VALUE
|
||||
ossl_bn_to_s(int argc, VALUE *argv, VALUE self)
|
||||
{
|
||||
|
@ -165,13 +185,13 @@ ossl_bn_to_s(int argc, VALUE *argv, VALUE self)
|
|||
case 0:
|
||||
len = BN_bn2mpi(bn, NULL);
|
||||
str = rb_str_new(0, len);
|
||||
if (BN_bn2mpi(bn, RSTRING(str)->ptr) != len)
|
||||
if (BN_bn2mpi(bn, RSTRING_PTR(str)) != len)
|
||||
ossl_raise(eBNError, NULL);
|
||||
break;
|
||||
case 2:
|
||||
len = BN_num_bytes(bn);
|
||||
str = rb_str_new(0, len);
|
||||
if (BN_bn2bin(bn, RSTRING(str)->ptr) != len)
|
||||
if (BN_bn2bin(bn, RSTRING_PTR(str)) != len)
|
||||
ossl_raise(eBNError, NULL);
|
||||
break;
|
||||
case 10:
|
||||
|
@ -189,6 +209,10 @@ ossl_bn_to_s(int argc, VALUE *argv, VALUE self)
|
|||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* bn.to_i => integer
|
||||
*/
|
||||
static VALUE
|
||||
ossl_bn_to_i(VALUE self)
|
||||
{
|
||||
|
@ -233,6 +257,11 @@ ossl_bn_coerce(VALUE self, VALUE other)
|
|||
}
|
||||
|
||||
#define BIGNUM_BOOL1(func) \
|
||||
/* \
|
||||
* call-seq: \
|
||||
* bn.##func -> true | false \
|
||||
* \
|
||||
*/ \
|
||||
static VALUE \
|
||||
ossl_bn_##func(VALUE self) \
|
||||
{ \
|
||||
|
@ -248,6 +277,11 @@ BIGNUM_BOOL1(is_one);
|
|||
BIGNUM_BOOL1(is_odd);
|
||||
|
||||
#define BIGNUM_1c(func) \
|
||||
/* \
|
||||
* call-seq: \
|
||||
* bn.##func -> aBN \
|
||||
* \
|
||||
*/ \
|
||||
static VALUE \
|
||||
ossl_bn_##func(VALUE self) \
|
||||
{ \
|
||||
|
@ -267,6 +301,11 @@ BIGNUM_BOOL1(is_odd);
|
|||
BIGNUM_1c(sqr);
|
||||
|
||||
#define BIGNUM_2(func) \
|
||||
/* \
|
||||
* call-seq: \
|
||||
* bn.##func(bn2) -> aBN \
|
||||
* \
|
||||
*/ \
|
||||
static VALUE \
|
||||
ossl_bn_##func(VALUE self, VALUE other) \
|
||||
{ \
|
||||
|
@ -287,6 +326,11 @@ BIGNUM_2(add);
|
|||
BIGNUM_2(sub);
|
||||
|
||||
#define BIGNUM_2c(func) \
|
||||
/* \
|
||||
* call-seq: \
|
||||
* bn.##func(bn2) -> aBN \
|
||||
* \
|
||||
*/ \
|
||||
static VALUE \
|
||||
ossl_bn_##func(VALUE self, VALUE other) \
|
||||
{ \
|
||||
|
@ -310,6 +354,10 @@ BIGNUM_2c(gcd);
|
|||
BIGNUM_2c(mod_sqr);
|
||||
BIGNUM_2c(mod_inverse);
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* bn1 / bn2 => [result, remainder]
|
||||
*/
|
||||
static VALUE
|
||||
ossl_bn_div(VALUE self, VALUE other)
|
||||
{
|
||||
|
@ -337,6 +385,11 @@ ossl_bn_div(VALUE self, VALUE other)
|
|||
}
|
||||
|
||||
#define BIGNUM_3c(func) \
|
||||
/* \
|
||||
* call-seq: \
|
||||
* bn.##func(bn1, bn2) -> aBN \
|
||||
* \
|
||||
*/ \
|
||||
static VALUE \
|
||||
ossl_bn_##func(VALUE self, VALUE other1, VALUE other2) \
|
||||
{ \
|
||||
|
@ -360,6 +413,11 @@ BIGNUM_3c(mod_mul);
|
|||
BIGNUM_3c(mod_exp);
|
||||
|
||||
#define BIGNUM_BIT(func) \
|
||||
/* \
|
||||
* call-seq: \
|
||||
* bn.##func(bit) -> self \
|
||||
* \
|
||||
*/ \
|
||||
static VALUE \
|
||||
ossl_bn_##func(VALUE self, VALUE bit) \
|
||||
{ \
|
||||
|
@ -374,6 +432,10 @@ BIGNUM_BIT(set_bit);
|
|||
BIGNUM_BIT(clear_bit);
|
||||
BIGNUM_BIT(mask_bits);
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* bn.bit_set?(bit) => true | false
|
||||
*/
|
||||
static VALUE
|
||||
ossl_bn_is_bit_set(VALUE self, VALUE bit)
|
||||
{
|
||||
|
@ -389,6 +451,11 @@ ossl_bn_is_bit_set(VALUE self, VALUE bit)
|
|||
}
|
||||
|
||||
#define BIGNUM_SHIFT(func) \
|
||||
/* \
|
||||
* call-seq: \
|
||||
* bn.##func(bits) -> aBN \
|
||||
* \
|
||||
*/ \
|
||||
static VALUE \
|
||||
ossl_bn_##func(VALUE self, VALUE bits) \
|
||||
{ \
|
||||
|
@ -410,7 +477,32 @@ ossl_bn_is_bit_set(VALUE self, VALUE bit)
|
|||
BIGNUM_SHIFT(lshift);
|
||||
BIGNUM_SHIFT(rshift);
|
||||
|
||||
#define BIGNUM_SELF_SHIFT(func) \
|
||||
/* \
|
||||
* call-seq: \
|
||||
* bn.##func!(bits) -> self \
|
||||
* \
|
||||
*/ \
|
||||
static VALUE \
|
||||
ossl_bn_self_##func(VALUE self, VALUE bits) \
|
||||
{ \
|
||||
BIGNUM *bn; \
|
||||
int b; \
|
||||
b = NUM2INT(bits); \
|
||||
GetBN(self, bn); \
|
||||
if (!BN_##func(bn, bn, b)) \
|
||||
ossl_raise(eBNError, NULL); \
|
||||
return self; \
|
||||
}
|
||||
BIGNUM_SELF_SHIFT(lshift);
|
||||
BIGNUM_SELF_SHIFT(rshift);
|
||||
|
||||
#define BIGNUM_RAND(func) \
|
||||
/* \
|
||||
* call-seq: \
|
||||
* BN.##func(bits [, fill [, odd]]) -> aBN \
|
||||
* \
|
||||
*/ \
|
||||
static VALUE \
|
||||
ossl_bn_s_##func(int argc, VALUE *argv, VALUE klass) \
|
||||
{ \
|
||||
|
@ -440,6 +532,11 @@ BIGNUM_RAND(rand);
|
|||
BIGNUM_RAND(pseudo_rand);
|
||||
|
||||
#define BIGNUM_RAND_RANGE(func) \
|
||||
/* \
|
||||
* call-seq: \
|
||||
* BN.##func(range) -> aBN \
|
||||
* \
|
||||
*/ \
|
||||
static VALUE \
|
||||
ossl_bn_s_##func##_range(VALUE klass, VALUE range) \
|
||||
{ \
|
||||
|
@ -458,6 +555,16 @@ BIGNUM_RAND(pseudo_rand);
|
|||
BIGNUM_RAND_RANGE(rand);
|
||||
BIGNUM_RAND_RANGE(pseudo_rand);
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* BN.generate_prime(bits, [, safe [, add [, rem]]]) => bn
|
||||
*
|
||||
* === Parameters
|
||||
* * +bits+ - integer
|
||||
* * +safe+ - boolean
|
||||
* * +add+ - BN
|
||||
* * +rem+ - BN
|
||||
*/
|
||||
static VALUE
|
||||
ossl_bn_s_generate_prime(int argc, VALUE *argv, VALUE klass)
|
||||
{
|
||||
|
@ -473,12 +580,8 @@ ossl_bn_s_generate_prime(int argc, VALUE *argv, VALUE klass)
|
|||
safe = 0;
|
||||
}
|
||||
if (!NIL_P(vadd)) {
|
||||
if (NIL_P(vrem)) {
|
||||
ossl_raise(rb_eArgError,
|
||||
"if ADD is specified, REM must be also given");
|
||||
}
|
||||
add = GetBNPtr(vadd);
|
||||
rem = GetBNPtr(vrem);
|
||||
rem = NIL_P(vrem) ? NULL : GetBNPtr(vrem);
|
||||
}
|
||||
if (!(result = BN_new())) {
|
||||
ossl_raise(eBNError, NULL);
|
||||
|
@ -493,6 +596,11 @@ ossl_bn_s_generate_prime(int argc, VALUE *argv, VALUE klass)
|
|||
}
|
||||
|
||||
#define BIGNUM_NUM(func) \
|
||||
/* \
|
||||
* call-seq: \
|
||||
* bn.##func -> integer \
|
||||
* \
|
||||
*/ \
|
||||
static VALUE \
|
||||
ossl_bn_##func(VALUE self) \
|
||||
{ \
|
||||
|
@ -522,6 +630,11 @@ ossl_bn_copy(VALUE self, VALUE other)
|
|||
}
|
||||
|
||||
#define BIGNUM_CMP(func) \
|
||||
/* \
|
||||
* call-seq: \
|
||||
* bn.##func(bn2) -> integer \
|
||||
* \
|
||||
*/ \
|
||||
static VALUE \
|
||||
ossl_bn_##func(VALUE self, VALUE other) \
|
||||
{ \
|
||||
|
@ -541,6 +654,14 @@ ossl_bn_eql(VALUE self, VALUE other)
|
|||
return Qfalse;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* bn.prime? => true | false
|
||||
* bn.prime?(checks) => true | false
|
||||
*
|
||||
* === Parameters
|
||||
* * +checks+ - integer
|
||||
*/
|
||||
static VALUE
|
||||
ossl_bn_is_prime(int argc, VALUE *argv, VALUE self)
|
||||
{
|
||||
|
@ -564,6 +685,16 @@ ossl_bn_is_prime(int argc, VALUE *argv, VALUE self)
|
|||
return Qnil;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* bn.prime_fasttest? => true | false
|
||||
* bn.prime_fasttest?(checks) => true | false
|
||||
* bn.prime_fasttest?(checks, trial_div) => true | false
|
||||
*
|
||||
* === Parameters
|
||||
* * +checks+ - integer
|
||||
* * +trial_div+ - boolean
|
||||
*/
|
||||
static VALUE
|
||||
ossl_bn_is_prime_fasttest(int argc, VALUE *argv, VALUE self)
|
||||
{
|
||||
|
@ -676,8 +807,10 @@ Init_ossl_bn()
|
|||
rb_define_method(cBN, "bit_set?", ossl_bn_is_bit_set, 1);
|
||||
rb_define_method(cBN, "mask_bits!", ossl_bn_mask_bits, 1);
|
||||
rb_define_method(cBN, "<<", ossl_bn_lshift, 1);
|
||||
/* lshift1 - DON'T IMPL. */
|
||||
rb_define_method(cBN, ">>", ossl_bn_rshift, 1);
|
||||
rb_define_method(cBN, "lshift!", ossl_bn_self_lshift, 1);
|
||||
rb_define_method(cBN, "rshift!", ossl_bn_self_rshift, 1);
|
||||
/* lshift1 - DON'T IMPL. */
|
||||
/* rshift1 - DON'T IMPL. */
|
||||
|
||||
/*
|
||||
|
|
|
@ -14,9 +14,12 @@
|
|||
extern VALUE cBN;
|
||||
extern VALUE eBNError;
|
||||
|
||||
VALUE ossl_bn_new(BIGNUM *);
|
||||
extern BN_CTX *ossl_bn_ctx;
|
||||
|
||||
VALUE ossl_bn_new(const BIGNUM *);
|
||||
BIGNUM *GetBNPtr(VALUE);
|
||||
void Init_ossl_bn(void);
|
||||
|
||||
|
||||
#endif /* _OSS_BN_H_ */
|
||||
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
/*
|
||||
* Classes
|
||||
*/
|
||||
VALUE mCipher;
|
||||
VALUE cCipher;
|
||||
VALUE eCipherError;
|
||||
|
||||
|
@ -84,6 +83,14 @@ ossl_cipher_alloc(VALUE klass)
|
|||
return obj;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* Cipher.new(string) -> cipher
|
||||
*
|
||||
* The string must contain a valid cipher name like "AES-128-CBC" or "3DES".
|
||||
*
|
||||
* A list of cipher names is available by calling OpenSSL::Cipher.ciphers.
|
||||
*/
|
||||
static VALUE
|
||||
ossl_cipher_initialize(VALUE self, VALUE str)
|
||||
{
|
||||
|
@ -124,6 +131,12 @@ add_cipher_name_to_ary(const OBJ_NAME *name, VALUE ary)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* Cipher.ciphers -> array[string...]
|
||||
*
|
||||
* Returns the names of all available ciphers in an array.
|
||||
*/
|
||||
static VALUE
|
||||
ossl_s_ciphers(VALUE self)
|
||||
{
|
||||
|
@ -141,6 +154,12 @@ ossl_s_ciphers(VALUE self)
|
|||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* cipher.reset -> self
|
||||
*
|
||||
* Internally calls EVP_CipherInit_ex(ctx, NULL, NULL, NULL, NULL, -1).
|
||||
*/
|
||||
static VALUE
|
||||
ossl_cipher_reset(VALUE self)
|
||||
{
|
||||
|
@ -167,22 +186,23 @@ ossl_cipher_init(int argc, VALUE *argv, VALUE self, int mode)
|
|||
* We deprecated the arguments for this method, but we decided
|
||||
* keeping this behaviour for backward compatibility.
|
||||
*/
|
||||
char *cname = rb_class2name(rb_obj_class(self));
|
||||
rb_warn("argumtents for %s#encrypt and %s#decrypt were deprecated; "
|
||||
"use %s#pkcs5_keyivgen to derive key and IV",
|
||||
cname, cname, cname);
|
||||
StringValue(pass);
|
||||
GetCipher(self, ctx);
|
||||
if (NIL_P(init_v)) memcpy(iv, "OpenSSL for Ruby rulez!", sizeof(iv));
|
||||
else{
|
||||
char *cname = rb_class2name(rb_obj_class(self));
|
||||
rb_warning("key derivation by %s#encrypt is deprecated; "
|
||||
"use %s::pkcs5_keyivgen instead", cname, cname);
|
||||
StringValue(init_v);
|
||||
if (EVP_MAX_IV_LENGTH > RSTRING(init_v)->len) {
|
||||
if (EVP_MAX_IV_LENGTH > RSTRING_LEN(init_v)) {
|
||||
memset(iv, 0, EVP_MAX_IV_LENGTH);
|
||||
memcpy(iv, RSTRING(init_v)->ptr, RSTRING(init_v)->len);
|
||||
memcpy(iv, RSTRING_PTR(init_v), RSTRING_LEN(init_v));
|
||||
}
|
||||
else memcpy(iv, RSTRING(init_v)->ptr, sizeof(iv));
|
||||
else memcpy(iv, RSTRING_PTR(init_v), sizeof(iv));
|
||||
}
|
||||
EVP_BytesToKey(EVP_CIPHER_CTX_cipher(ctx), EVP_md5(), iv,
|
||||
RSTRING(pass)->ptr, RSTRING(pass)->len, 1, key, NULL);
|
||||
RSTRING_PTR(pass), RSTRING_LEN(pass), 1, key, NULL);
|
||||
p_key = key;
|
||||
p_iv = iv;
|
||||
}
|
||||
|
@ -196,18 +216,54 @@ ossl_cipher_init(int argc, VALUE *argv, VALUE self, int mode)
|
|||
return self;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* cipher.encrypt -> self
|
||||
*
|
||||
* Make sure to call .encrypt or .decrypt before using any of the following methods:
|
||||
* * [key=, iv=, random_key, random_iv, pkcs5_keyivgen]
|
||||
*
|
||||
* Internally calls EVP_CipherInit_ex(ctx, NULL, NULL, NULL, NULL, 1).
|
||||
*/
|
||||
static VALUE
|
||||
ossl_cipher_encrypt(int argc, VALUE *argv, VALUE self)
|
||||
{
|
||||
return ossl_cipher_init(argc, argv, self, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* cipher.decrypt -> self
|
||||
*
|
||||
* Make sure to call .encrypt or .decrypt before using any of the following methods:
|
||||
* * [key=, iv=, random_key, random_iv, pkcs5_keyivgen]
|
||||
*
|
||||
* Internally calls EVP_CipherInit_ex(ctx, NULL, NULL, NULL, NULL, 0).
|
||||
*/
|
||||
static VALUE
|
||||
ossl_cipher_decrypt(int argc, VALUE *argv, VALUE self)
|
||||
{
|
||||
return ossl_cipher_init(argc, argv, self, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* cipher.pkcs5_keyivgen(pass [, salt [, iterations [, digest]]] ) -> 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, or DES
|
||||
* with MD5 or SHA1. Using anything else (like AES) will generate the key/iv using an
|
||||
* OpenSSL specific method. Use a PKCS5 v2 key generation method 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'
|
||||
*
|
||||
* A minimum of 1000 iterations is recommended.
|
||||
*
|
||||
*/
|
||||
static VALUE
|
||||
ossl_cipher_pkcs5_keyivgen(int argc, VALUE *argv, VALUE self)
|
||||
{
|
||||
|
@ -221,15 +277,15 @@ ossl_cipher_pkcs5_keyivgen(int argc, VALUE *argv, VALUE self)
|
|||
StringValue(vpass);
|
||||
if(!NIL_P(vsalt)){
|
||||
StringValue(vsalt);
|
||||
if(RSTRING(vsalt)->len != PKCS5_SALT_LEN)
|
||||
if(RSTRING_LEN(vsalt) != PKCS5_SALT_LEN)
|
||||
rb_raise(eCipherError, "salt must be an 8-octet string");
|
||||
salt = RSTRING(vsalt)->ptr;
|
||||
salt = RSTRING_PTR(vsalt);
|
||||
}
|
||||
iter = NIL_P(viter) ? 2048 : NUM2INT(viter);
|
||||
digest = NIL_P(vdigest) ? EVP_md5() : GetDigestPtr(vdigest);
|
||||
GetCipher(self, ctx);
|
||||
EVP_BytesToKey(EVP_CIPHER_CTX_cipher(ctx), digest, salt,
|
||||
RSTRING(vpass)->ptr, RSTRING(vpass)->len, iter, key, iv);
|
||||
RSTRING_PTR(vpass), RSTRING_LEN(vpass), iter, key, iv);
|
||||
if (EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, -1) != 1)
|
||||
ossl_raise(eCipherError, NULL);
|
||||
OPENSSL_cleanse(key, sizeof key);
|
||||
|
@ -238,29 +294,16 @@ ossl_cipher_pkcs5_keyivgen(int argc, VALUE *argv, VALUE self)
|
|||
return Qnil;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
ossl_cipher_update(VALUE self, VALUE data)
|
||||
{
|
||||
EVP_CIPHER_CTX *ctx;
|
||||
char *in;
|
||||
int in_len, out_len;
|
||||
VALUE str;
|
||||
|
||||
StringValue(data);
|
||||
in = RSTRING(data)->ptr;
|
||||
if ((in_len = RSTRING(data)->len) == 0)
|
||||
rb_raise(rb_eArgError, "data must not be empty");
|
||||
GetCipher(self, ctx);
|
||||
str = rb_str_new(0, in_len+EVP_CIPHER_CTX_block_size(ctx));
|
||||
if (!EVP_CipherUpdate(ctx, RSTRING(str)->ptr, &out_len, in, in_len))
|
||||
ossl_raise(eCipherError, NULL);
|
||||
assert(out_len < RSTRING(str)->len);
|
||||
RSTRING(str)->len = out_len;
|
||||
RSTRING(str)->ptr[out_len] = 0;
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* cipher << data -> string
|
||||
*
|
||||
* === Parameters
|
||||
* +data+ is a nonempty string.
|
||||
*
|
||||
* This method is deprecated and not available in 1.9.x or later.
|
||||
*/
|
||||
static VALUE
|
||||
ossl_cipher_update_deprecated(VALUE self, VALUE data)
|
||||
{
|
||||
|
@ -268,9 +311,58 @@ ossl_cipher_update_deprecated(VALUE self, VALUE data)
|
|||
|
||||
cname = rb_class2name(rb_obj_class(self));
|
||||
rb_warning("%s#<< is deprecated; use %s#update instead", cname, cname);
|
||||
return ossl_cipher_update(self, data);
|
||||
return rb_funcall(self, rb_intern("update"), 1, data);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* cipher.update(data [, buffer]) -> string or buffer
|
||||
*
|
||||
* === Parameters
|
||||
* +data+ is a nonempty string.
|
||||
* +buffer+ is an optional string to store the result.
|
||||
*/
|
||||
static VALUE
|
||||
ossl_cipher_update(int argc, VALUE *argv, VALUE self)
|
||||
{
|
||||
EVP_CIPHER_CTX *ctx;
|
||||
char *in;
|
||||
int in_len, out_len;
|
||||
VALUE data, str;
|
||||
|
||||
rb_scan_args(argc, argv, "11", &data, &str);
|
||||
|
||||
StringValue(data);
|
||||
in = RSTRING_PTR(data);
|
||||
if ((in_len = RSTRING_LEN(data)) == 0)
|
||||
rb_raise(rb_eArgError, "data must not be empty");
|
||||
GetCipher(self, ctx);
|
||||
out_len = in_len+EVP_CIPHER_CTX_block_size(ctx);
|
||||
|
||||
if (NIL_P(str)) {
|
||||
str = rb_str_new(0, out_len);
|
||||
} else {
|
||||
StringValue(str);
|
||||
rb_str_resize(str, out_len);
|
||||
}
|
||||
|
||||
if (!EVP_CipherUpdate(ctx, RSTRING_PTR(str), &out_len, in, in_len))
|
||||
ossl_raise(eCipherError, NULL);
|
||||
assert(out_len < RSTRING_LEN(str));
|
||||
rb_str_set_len(str, out_len);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* cipher.final -> aString
|
||||
*
|
||||
* Returns the remaining data held in the cipher object. Further calls to update() or final() will return garbage.
|
||||
*
|
||||
* See EVP_CipherFinal_ex for further information.
|
||||
*/
|
||||
static VALUE
|
||||
ossl_cipher_final(VALUE self)
|
||||
{
|
||||
|
@ -280,15 +372,20 @@ ossl_cipher_final(VALUE self)
|
|||
|
||||
GetCipher(self, ctx);
|
||||
str = rb_str_new(0, EVP_CIPHER_CTX_block_size(ctx));
|
||||
if (!EVP_CipherFinal_ex(ctx, RSTRING(str)->ptr, &out_len))
|
||||
if (!EVP_CipherFinal_ex(ctx, RSTRING_PTR(str), &out_len))
|
||||
ossl_raise(eCipherError, NULL);
|
||||
assert(out_len <= RSTRING(str)->len);
|
||||
RSTRING(str)->len = out_len;
|
||||
RSTRING(str)->ptr[out_len] = 0;
|
||||
assert(out_len <= RSTRING_LEN(str));
|
||||
rb_str_set_len(str, out_len);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* cipher.name -> string
|
||||
*
|
||||
* Returns the name of the cipher which may differ slightly from the original name provided.
|
||||
*/
|
||||
static VALUE
|
||||
ossl_cipher_name(VALUE self)
|
||||
{
|
||||
|
@ -299,6 +396,14 @@ ossl_cipher_name(VALUE self)
|
|||
return rb_str_new2(EVP_CIPHER_name(EVP_CIPHER_CTX_cipher(ctx)));
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* cipher.key = string -> string
|
||||
*
|
||||
* Sets the cipher key.
|
||||
*
|
||||
* Only call this method after calling cipher.encrypt or cipher.decrypt.
|
||||
*/
|
||||
static VALUE
|
||||
ossl_cipher_set_key(VALUE self, VALUE key)
|
||||
{
|
||||
|
@ -307,15 +412,23 @@ ossl_cipher_set_key(VALUE self, VALUE key)
|
|||
StringValue(key);
|
||||
GetCipher(self, ctx);
|
||||
|
||||
if (RSTRING(key)->len < EVP_CIPHER_CTX_key_length(ctx))
|
||||
if (RSTRING_LEN(key) < EVP_CIPHER_CTX_key_length(ctx))
|
||||
ossl_raise(eCipherError, "key length too short");
|
||||
|
||||
if (EVP_CipherInit_ex(ctx, NULL, NULL, RSTRING(key)->ptr, NULL, -1) != 1)
|
||||
if (EVP_CipherInit_ex(ctx, NULL, NULL, RSTRING_PTR(key), NULL, -1) != 1)
|
||||
ossl_raise(eCipherError, NULL);
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* cipher.iv = string -> string
|
||||
*
|
||||
* Sets the cipher iv.
|
||||
*
|
||||
* Only call this method after calling cipher.encrypt or cipher.decrypt.
|
||||
*/
|
||||
static VALUE
|
||||
ossl_cipher_set_iv(VALUE self, VALUE iv)
|
||||
{
|
||||
|
@ -324,20 +437,32 @@ ossl_cipher_set_iv(VALUE self, VALUE iv)
|
|||
StringValue(iv);
|
||||
GetCipher(self, ctx);
|
||||
|
||||
if (RSTRING(iv)->len < EVP_CIPHER_CTX_iv_length(ctx))
|
||||
if (RSTRING_LEN(iv) < EVP_CIPHER_CTX_iv_length(ctx))
|
||||
ossl_raise(eCipherError, "iv length too short");
|
||||
|
||||
if (EVP_CipherInit_ex(ctx, NULL, NULL, NULL, RSTRING(iv)->ptr, -1) != 1)
|
||||
if (EVP_CipherInit_ex(ctx, NULL, NULL, NULL, RSTRING_PTR(iv), -1) != 1)
|
||||
ossl_raise(eCipherError, NULL);
|
||||
|
||||
return iv;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* cipher.key_length = integer -> integer
|
||||
*
|
||||
* Sets the key length of the cipher. If the cipher is a fixed length cipher then attempting to set the key
|
||||
* length to any value other than the fixed value is an error.
|
||||
*
|
||||
* Under normal circumstances you do not need to call this method (and probably shouldn't).
|
||||
*
|
||||
* See EVP_CIPHER_CTX_set_key_length for further information.
|
||||
*/
|
||||
static VALUE
|
||||
ossl_cipher_set_key_length(VALUE self, VALUE key_length)
|
||||
{
|
||||
EVP_CIPHER_CTX *ctx;
|
||||
int len = NUM2INT(key_length);
|
||||
EVP_CIPHER_CTX *ctx;
|
||||
|
||||
GetCipher(self, ctx);
|
||||
if (EVP_CIPHER_CTX_set_key_length(ctx, len) != 1)
|
||||
|
@ -346,6 +471,16 @@ ossl_cipher_set_key_length(VALUE self, VALUE key_length)
|
|||
return key_length;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* cipher.padding = integer -> integer
|
||||
*
|
||||
* Enables or disables padding. By default encryption operations are padded using standard block padding and the
|
||||
* padding is checked and removed when decrypting. If the pad parameter is zero then no padding is performed, the
|
||||
* total amount of data encrypted or decrypted must then be a multiple of the block size or an error will occur.
|
||||
*
|
||||
* See EVP_CIPHER_CTX_set_padding for further information.
|
||||
*/
|
||||
static VALUE
|
||||
ossl_cipher_set_padding(VALUE self, VALUE padding)
|
||||
{
|
||||
|
@ -374,6 +509,27 @@ CIPHER_0ARG_INT(key_length)
|
|||
CIPHER_0ARG_INT(iv_length)
|
||||
CIPHER_0ARG_INT(block_size)
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* call-seq:
|
||||
* cipher.key_length -> integer
|
||||
*
|
||||
*/
|
||||
static VALUE ossl_cipher_key_length() { }
|
||||
/*
|
||||
* call-seq:
|
||||
* cipher.iv_length -> integer
|
||||
*
|
||||
*/
|
||||
static VALUE ossl_cipher_iv_length() { }
|
||||
/*
|
||||
* call-seq:
|
||||
* cipher.block_size -> integer
|
||||
*
|
||||
*/
|
||||
static VALUE ossl_cipher_block_size() { }
|
||||
#endif
|
||||
|
||||
/*
|
||||
* INIT
|
||||
*/
|
||||
|
@ -383,21 +539,21 @@ Init_ossl_cipher(void)
|
|||
#if 0 /* let rdoc know about mOSSL */
|
||||
mOSSL = rb_define_module("OpenSSL");
|
||||
#endif
|
||||
|
||||
mCipher = rb_define_module_under(mOSSL, "Cipher");
|
||||
eCipherError = rb_define_class_under(mOSSL, "CipherError", eOSSLError);
|
||||
cCipher = rb_define_class_under(mCipher, "Cipher", rb_cObject);
|
||||
cCipher = rb_define_class_under(mOSSL, "Cipher", rb_cObject);
|
||||
eCipherError = rb_define_class_under(cCipher, "CipherError", eOSSLError);
|
||||
|
||||
rb_define_alloc_func(cCipher, ossl_cipher_alloc);
|
||||
rb_define_copy_func(cCipher, ossl_cipher_copy);
|
||||
rb_define_module_function(mCipher, "ciphers", ossl_s_ciphers, 0);
|
||||
rb_define_module_function(cCipher, "ciphers", ossl_s_ciphers, 0);
|
||||
rb_define_method(cCipher, "initialize", ossl_cipher_initialize, 1);
|
||||
rb_define_method(cCipher, "reset", ossl_cipher_reset, 0);
|
||||
rb_define_method(cCipher, "encrypt", ossl_cipher_encrypt, -1);
|
||||
rb_define_method(cCipher, "decrypt", ossl_cipher_decrypt, -1);
|
||||
rb_define_method(cCipher, "pkcs5_keyivgen", ossl_cipher_pkcs5_keyivgen, -1);
|
||||
rb_define_method(cCipher, "update", ossl_cipher_update, 1);
|
||||
rb_define_method(cCipher, "update", ossl_cipher_update, -1);
|
||||
#if RUBY_VERSION_CODE < 190
|
||||
rb_define_method(cCipher, "<<", ossl_cipher_update_deprecated, 1);
|
||||
#endif
|
||||
rb_define_method(cCipher, "final", ossl_cipher_final, 0);
|
||||
rb_define_method(cCipher, "name", ossl_cipher_name, 0);
|
||||
rb_define_method(cCipher, "key=", ossl_cipher_set_key, 1);
|
||||
|
@ -408,3 +564,4 @@ Init_ossl_cipher(void)
|
|||
rb_define_method(cCipher, "block_size", ossl_cipher_block_size, 0);
|
||||
rb_define_method(cCipher, "padding=", ossl_cipher_set_padding, 1);
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
#if !defined(_OSSL_CIPHER_H_)
|
||||
#define _OSSL_CIPHER_H_
|
||||
|
||||
extern VALUE mCipher;
|
||||
extern VALUE cCipher;
|
||||
extern VALUE eCipherError;
|
||||
|
||||
|
|
|
@ -171,16 +171,16 @@ ossl_config_add_value(VALUE self, VALUE section, VALUE name, VALUE value)
|
|||
StringValue(name);
|
||||
StringValue(value);
|
||||
GetConfig(self, conf);
|
||||
if(!(sv = _CONF_get_section(conf, RSTRING(section)->ptr))){
|
||||
if(!(sv = _CONF_new_section(conf, RSTRING(section)->ptr))){
|
||||
if(!(sv = _CONF_get_section(conf, RSTRING_PTR(section)))){
|
||||
if(!(sv = _CONF_new_section(conf, RSTRING_PTR(section)))){
|
||||
ossl_raise(eConfigError, NULL);
|
||||
}
|
||||
}
|
||||
if(!(cv = OPENSSL_malloc(sizeof(CONF_VALUE)))){
|
||||
ossl_raise(eConfigError, NULL);
|
||||
}
|
||||
cv->name = BUF_strdup(RSTRING(name)->ptr);
|
||||
cv->value = BUF_strdup(RSTRING(value)->ptr);
|
||||
cv->name = BUF_strdup(RSTRING_PTR(name));
|
||||
cv->value = BUF_strdup(RSTRING_PTR(value));
|
||||
if(!cv->name || !cv->value || !_CONF_add_string(conf, sv, cv)){
|
||||
OPENSSL_free(cv->name);
|
||||
OPENSSL_free(cv->value);
|
||||
|
@ -201,7 +201,7 @@ ossl_config_get_value(VALUE self, VALUE section, VALUE name)
|
|||
StringValue(section);
|
||||
StringValue(name);
|
||||
GetConfig(self, conf);
|
||||
str = NCONF_get_string(conf, RSTRING(section)->ptr, RSTRING(name)->ptr);
|
||||
str = NCONF_get_string(conf, RSTRING_PTR(section), RSTRING_PTR(name));
|
||||
if(!str){
|
||||
ERR_clear_error();
|
||||
return Qnil;
|
||||
|
@ -246,7 +246,7 @@ static VALUE
|
|||
ossl_config_set_section(VALUE self, VALUE section, VALUE hash)
|
||||
{
|
||||
VALUE arg[2] = { self, section };
|
||||
rb_iterate(rb_each, hash, set_conf_section_i, (VALUE)arg);
|
||||
rb_block_call(hash, rb_intern("each"), 0, 0, set_conf_section_i, (VALUE)arg);
|
||||
return hash;
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
/*
|
||||
* Classes
|
||||
*/
|
||||
VALUE mDigest;
|
||||
VALUE cDigest;
|
||||
VALUE eDigestError;
|
||||
|
||||
|
@ -36,11 +35,23 @@ static VALUE ossl_digest_alloc(VALUE klass);
|
|||
const EVP_MD *
|
||||
GetDigestPtr(VALUE obj)
|
||||
{
|
||||
const EVP_MD *md;
|
||||
|
||||
if (TYPE(obj) == T_STRING) {
|
||||
const char *name = STR2CSTR(obj);
|
||||
|
||||
md = EVP_get_digestbyname(name);
|
||||
if (!md)
|
||||
ossl_raise(rb_eRuntimeError, "Unsupported digest algorithm (%s).", name);
|
||||
} else {
|
||||
EVP_MD_CTX *ctx;
|
||||
|
||||
SafeGetDigest(obj, ctx);
|
||||
|
||||
return EVP_MD_CTX_md(ctx); /*== ctx->digest*/
|
||||
md = EVP_MD_CTX_md(ctx); /*== ctx->digest*/
|
||||
}
|
||||
|
||||
return md;
|
||||
}
|
||||
|
||||
VALUE
|
||||
|
@ -77,6 +88,11 @@ ossl_digest_alloc(VALUE klass)
|
|||
|
||||
VALUE ossl_digest_update(VALUE, VALUE);
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* Digest.new(string) -> digest
|
||||
*
|
||||
*/
|
||||
static VALUE
|
||||
ossl_digest_initialize(int argc, VALUE *argv, VALUE self)
|
||||
{
|
||||
|
@ -118,6 +134,11 @@ ossl_digest_copy(VALUE self, VALUE other)
|
|||
return self;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* digest.reset -> self
|
||||
*
|
||||
*/
|
||||
static VALUE
|
||||
ossl_digest_reset(VALUE self)
|
||||
{
|
||||
|
@ -129,6 +150,11 @@ ossl_digest_reset(VALUE self)
|
|||
return self;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* digest.update(string) -> aString
|
||||
*
|
||||
*/
|
||||
VALUE
|
||||
ossl_digest_update(VALUE self, VALUE data)
|
||||
{
|
||||
|
@ -136,7 +162,7 @@ ossl_digest_update(VALUE self, VALUE data)
|
|||
|
||||
StringValue(data);
|
||||
GetDigest(self, ctx);
|
||||
EVP_DigestUpdate(ctx, RSTRING(data)->ptr, RSTRING(data)->len);
|
||||
EVP_DigestUpdate(ctx, RSTRING_PTR(data), RSTRING_LEN(data));
|
||||
|
||||
return self;
|
||||
}
|
||||
|
@ -157,6 +183,11 @@ digest_final(EVP_MD_CTX *ctx, char **buf, int *buf_len)
|
|||
EVP_MD_CTX_cleanup(&final);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* digest.final -> aString
|
||||
*
|
||||
*/
|
||||
static VALUE
|
||||
ossl_digest_digest(VALUE self)
|
||||
{
|
||||
|
@ -172,6 +203,11 @@ ossl_digest_digest(VALUE self)
|
|||
return digest;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* digest.hexdigest -> aString
|
||||
*
|
||||
*/
|
||||
static VALUE
|
||||
ossl_digest_hexdigest(VALUE self)
|
||||
{
|
||||
|
@ -212,6 +248,11 @@ ossl_digest_s_hexdigest(VALUE klass, VALUE str, VALUE data)
|
|||
return ossl_digest_hexdigest(obj);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* digest1 == digest2 -> true | false
|
||||
*
|
||||
*/
|
||||
static VALUE
|
||||
ossl_digest_equal(VALUE self, VALUE other)
|
||||
{
|
||||
|
@ -225,12 +266,12 @@ ossl_digest_equal(VALUE self, VALUE other)
|
|||
str2 = other;
|
||||
}
|
||||
GetDigest(self, ctx);
|
||||
if (RSTRING(str2)->len == EVP_MD_CTX_size(ctx)) {
|
||||
if (RSTRING_LEN(str2) == EVP_MD_CTX_size(ctx)) {
|
||||
str1 = ossl_digest_digest(self);
|
||||
} else {
|
||||
str1 = ossl_digest_hexdigest(self);
|
||||
}
|
||||
if (RSTRING(str1)->len == RSTRING(str2)->len
|
||||
if (RSTRING_LEN(str1) == RSTRING_LEN(str2)
|
||||
&& rb_str_cmp(str1, str2) == 0) {
|
||||
return Qtrue;
|
||||
}
|
||||
|
@ -238,6 +279,11 @@ ossl_digest_equal(VALUE self, VALUE other)
|
|||
return Qfalse;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* digest.name -> string
|
||||
*
|
||||
*/
|
||||
static VALUE
|
||||
ossl_digest_name(VALUE self)
|
||||
{
|
||||
|
@ -248,6 +294,12 @@ ossl_digest_name(VALUE self)
|
|||
return rb_str_new2(EVP_MD_name(EVP_MD_CTX_md(ctx)));
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* digest.size -> integer
|
||||
*
|
||||
* Returns the output size of the digest.
|
||||
*/
|
||||
static VALUE
|
||||
ossl_digest_size(VALUE self)
|
||||
{
|
||||
|
@ -268,11 +320,8 @@ Init_ossl_digest()
|
|||
mOSSL = rb_define_module("OpenSSL");
|
||||
#endif
|
||||
|
||||
mDigest = rb_define_module_under(mOSSL, "Digest");
|
||||
|
||||
eDigestError = rb_define_class_under(mDigest, "DigestError", eOSSLError);
|
||||
|
||||
cDigest = rb_define_class_under(mDigest, "Digest", rb_cObject);
|
||||
cDigest = rb_define_class_under(mOSSL, "Digest", rb_cObject);
|
||||
eDigestError = rb_define_class_under(cDigest, "DigestError", eOSSLError);
|
||||
|
||||
rb_define_alloc_func(cDigest, ossl_digest_alloc);
|
||||
rb_define_singleton_method(cDigest, "digest", ossl_digest_s_digest, 2);
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
#if !defined(_OSSL_DIGEST_H_)
|
||||
#define _OSSL_DIGEST_H_
|
||||
|
||||
extern VALUE mDigest;
|
||||
extern VALUE cDigest;
|
||||
extern VALUE eDigestError;
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ VALUE eEngineError;
|
|||
*/
|
||||
#define OSSL_ENGINE_LOAD_IF_MATCH(x) \
|
||||
do{\
|
||||
if(!strcmp(#x, RSTRING(name)->ptr)){\
|
||||
if(!strcmp(#x, RSTRING_PTR(name))){\
|
||||
ENGINE_load_##x();\
|
||||
return Qtrue;\
|
||||
}\
|
||||
|
@ -75,7 +75,7 @@ ossl_engine_s_load(int argc, VALUE *argv, VALUE klass)
|
|||
OSSL_ENGINE_LOAD_IF_MATCH(openbsd_dev_crypto);
|
||||
#endif
|
||||
OSSL_ENGINE_LOAD_IF_MATCH(openssl);
|
||||
rb_warning("no such builtin loader for `%s'", RSTRING(name)->ptr);
|
||||
rb_warning("no such builtin loader for `%s'", RSTRING_PTR(name));
|
||||
return Qnil;
|
||||
#endif /* HAVE_ENGINE_LOAD_BUILTIN_ENGINES */
|
||||
}
|
||||
|
@ -112,7 +112,7 @@ ossl_engine_s_by_id(VALUE klass, VALUE id)
|
|||
|
||||
StringValue(id);
|
||||
ossl_engine_s_load(1, &id, klass);
|
||||
if(!(e = ENGINE_by_id(RSTRING(id)->ptr)))
|
||||
if(!(e = ENGINE_by_id(RSTRING_PTR(id))))
|
||||
ossl_raise(eEngineError, NULL);
|
||||
WrapEngine(klass, obj, e);
|
||||
if(rb_block_given_p()) rb_yield(obj);
|
||||
|
@ -281,8 +281,8 @@ ossl_engine_ctrl_cmd(int argc, VALUE *argv, VALUE self)
|
|||
rb_scan_args(argc, argv, "11", &cmd, &val);
|
||||
StringValue(cmd);
|
||||
if (!NIL_P(val)) StringValue(val);
|
||||
ret = ENGINE_ctrl_cmd_string(e, RSTRING(cmd)->ptr,
|
||||
NIL_P(val) ? NULL : RSTRING(val)->ptr, 0);
|
||||
ret = ENGINE_ctrl_cmd_string(e, RSTRING_PTR(cmd),
|
||||
NIL_P(val) ? NULL : RSTRING_PTR(val), 0);
|
||||
if (!ret) ossl_raise(eEngineError, NULL);
|
||||
|
||||
return self;
|
||||
|
|
|
@ -57,6 +57,12 @@ ossl_hmac_alloc(VALUE klass)
|
|||
return obj;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* HMAC.new(key, digest) -> hmac
|
||||
*
|
||||
*/
|
||||
static VALUE
|
||||
ossl_hmac_initialize(VALUE self, VALUE key, VALUE digest)
|
||||
{
|
||||
|
@ -64,7 +70,7 @@ ossl_hmac_initialize(VALUE self, VALUE key, VALUE digest)
|
|||
|
||||
StringValue(key);
|
||||
GetHMAC(self, ctx);
|
||||
HMAC_Init_ex(ctx, RSTRING(key)->ptr, RSTRING(key)->len,
|
||||
HMAC_Init_ex(ctx, RSTRING_PTR(key), RSTRING_LEN(key),
|
||||
GetDigestPtr(digest), NULL);
|
||||
|
||||
return self;
|
||||
|
@ -87,6 +93,11 @@ ossl_hmac_copy(VALUE self, VALUE other)
|
|||
return self;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* hmac.update(string) -> self
|
||||
*
|
||||
*/
|
||||
static VALUE
|
||||
ossl_hmac_update(VALUE self, VALUE data)
|
||||
{
|
||||
|
@ -94,7 +105,7 @@ ossl_hmac_update(VALUE self, VALUE data)
|
|||
|
||||
StringValue(data);
|
||||
GetHMAC(self, ctx);
|
||||
HMAC_Update(ctx, RSTRING(data)->ptr, RSTRING(data)->len);
|
||||
HMAC_Update(ctx, RSTRING_PTR(data), RSTRING_LEN(data));
|
||||
|
||||
return self;
|
||||
}
|
||||
|
@ -116,6 +127,11 @@ hmac_final(HMAC_CTX *ctx, char **buf, int *buf_len)
|
|||
HMAC_CTX_cleanup(&final);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* hmac.digest -> aString
|
||||
*
|
||||
*/
|
||||
static VALUE
|
||||
ossl_hmac_digest(VALUE self)
|
||||
{
|
||||
|
@ -131,6 +147,11 @@ ossl_hmac_digest(VALUE self)
|
|||
return digest;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* hmac.hexdigest -> aString
|
||||
*
|
||||
*/
|
||||
static VALUE
|
||||
ossl_hmac_hexdigest(VALUE self)
|
||||
{
|
||||
|
@ -151,6 +172,27 @@ ossl_hmac_hexdigest(VALUE self)
|
|||
return hexdigest;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* hmac.reset -> self
|
||||
*
|
||||
*/
|
||||
static VALUE
|
||||
ossl_hmac_reset(VALUE self)
|
||||
{
|
||||
HMAC_CTX *ctx;
|
||||
|
||||
GetHMAC(self, ctx);
|
||||
HMAC_Init_ex(ctx, NULL, 0, NULL, NULL);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* HMAC.digest(digest, key, data) -> aString
|
||||
*
|
||||
*/
|
||||
static VALUE
|
||||
ossl_hmac_s_digest(VALUE klass, VALUE digest, VALUE key, VALUE data)
|
||||
{
|
||||
|
@ -159,12 +201,17 @@ ossl_hmac_s_digest(VALUE klass, VALUE digest, VALUE key, VALUE data)
|
|||
|
||||
StringValue(key);
|
||||
StringValue(data);
|
||||
buf = HMAC(GetDigestPtr(digest), RSTRING(key)->ptr, RSTRING(key)->len,
|
||||
RSTRING(data)->ptr, RSTRING(data)->len, NULL, &buf_len);
|
||||
buf = HMAC(GetDigestPtr(digest), RSTRING_PTR(key), RSTRING_LEN(key),
|
||||
RSTRING_PTR(data), RSTRING_LEN(data), NULL, &buf_len);
|
||||
|
||||
return rb_str_new(buf, buf_len);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* HMAC.digest(digest, key, data) -> aString
|
||||
*
|
||||
*/
|
||||
static VALUE
|
||||
ossl_hmac_s_hexdigest(VALUE klass, VALUE digest, VALUE key, VALUE data)
|
||||
{
|
||||
|
@ -175,8 +222,8 @@ ossl_hmac_s_hexdigest(VALUE klass, VALUE digest, VALUE key, VALUE data)
|
|||
StringValue(key);
|
||||
StringValue(data);
|
||||
|
||||
buf = HMAC(GetDigestPtr(digest), RSTRING(key)->ptr, RSTRING(key)->len,
|
||||
RSTRING(data)->ptr, RSTRING(data)->len, NULL, &buf_len);
|
||||
buf = HMAC(GetDigestPtr(digest), RSTRING_PTR(key), RSTRING_LEN(key),
|
||||
RSTRING_PTR(data), RSTRING_LEN(data), NULL, &buf_len);
|
||||
if (string2hex(buf, buf_len, &hexbuf, NULL) != 2 * buf_len) {
|
||||
ossl_raise(eHMACError, "Cannot convert buf to hexbuf");
|
||||
}
|
||||
|
@ -206,6 +253,7 @@ Init_ossl_hmac()
|
|||
rb_define_method(cHMAC, "initialize", ossl_hmac_initialize, 2);
|
||||
rb_define_copy_func(cHMAC, ossl_hmac_copy);
|
||||
|
||||
rb_define_method(cHMAC, "reset", ossl_hmac_reset, 0);
|
||||
rb_define_method(cHMAC, "update", ossl_hmac_update, 1);
|
||||
rb_define_alias(cHMAC, "<<", "update");
|
||||
rb_define_method(cHMAC, "digest", ossl_hmac_digest, 0);
|
||||
|
|
|
@ -62,9 +62,9 @@ ossl_spki_initialize(int argc, VALUE *argv, VALUE self)
|
|||
return self;
|
||||
}
|
||||
StringValue(buffer);
|
||||
if (!(spki = NETSCAPE_SPKI_b64_decode(RSTRING(buffer)->ptr, -1))) {
|
||||
p = RSTRING(buffer)->ptr;
|
||||
if (!(spki = d2i_NETSCAPE_SPKI(NULL, &p, RSTRING(buffer)->len))) {
|
||||
if (!(spki = NETSCAPE_SPKI_b64_decode(RSTRING_PTR(buffer), -1))) {
|
||||
p = RSTRING_PTR(buffer);
|
||||
if (!(spki = d2i_NETSCAPE_SPKI(NULL, &p, RSTRING_LEN(buffer)))) {
|
||||
ossl_raise(eSPKIError, NULL);
|
||||
}
|
||||
}
|
||||
|
@ -87,7 +87,7 @@ ossl_spki_to_der(VALUE self)
|
|||
if ((len = i2d_NETSCAPE_SPKI(spki, NULL)) <= 0)
|
||||
ossl_raise(eX509CertError, NULL);
|
||||
str = rb_str_new(0, len);
|
||||
p = RSTRING(str)->ptr;
|
||||
p = RSTRING_PTR(str);
|
||||
if (i2d_NETSCAPE_SPKI(spki, &p) <= 0)
|
||||
ossl_raise(eX509CertError, NULL);
|
||||
ossl_str_adjust(str, p);
|
||||
|
@ -183,8 +183,8 @@ ossl_spki_set_challenge(VALUE self, VALUE str)
|
|||
|
||||
StringValue(str);
|
||||
GetSPKI(self, spki);
|
||||
if (!ASN1_STRING_set(spki->spkac->challenge, RSTRING(str)->ptr,
|
||||
RSTRING(str)->len)) {
|
||||
if (!ASN1_STRING_set(spki->spkac->challenge, RSTRING_PTR(str),
|
||||
RSTRING_LEN(str))) {
|
||||
ossl_raise(eSPKIError, NULL);
|
||||
}
|
||||
|
||||
|
|
|
@ -109,9 +109,9 @@ ossl_ocspreq_initialize(int argc, VALUE *argv, VALUE self)
|
|||
if(!NIL_P(arg)){
|
||||
arg = ossl_to_der_if_possible(arg);
|
||||
StringValue(arg);
|
||||
p = (unsigned char*)RSTRING(arg)->ptr;
|
||||
p = (unsigned char*)RSTRING_PTR(arg);
|
||||
if(!d2i_OCSP_REQUEST((OCSP_REQUEST**)&DATA_PTR(self), &p,
|
||||
RSTRING(arg)->len)){
|
||||
RSTRING_LEN(arg))){
|
||||
ossl_raise(eOCSPError, "cannot load DER encoded request");
|
||||
}
|
||||
}
|
||||
|
@ -134,7 +134,7 @@ ossl_ocspreq_add_nonce(int argc, VALUE *argv, VALUE self)
|
|||
else{
|
||||
StringValue(val);
|
||||
GetOCSPReq(self, req);
|
||||
ret = OCSP_request_add1_nonce(req, RSTRING(val)->ptr, RSTRING(val)->len);
|
||||
ret = OCSP_request_add1_nonce(req, RSTRING_PTR(val), RSTRING_LEN(val));
|
||||
}
|
||||
if(!ret) ossl_raise(eOCSPError, NULL);
|
||||
|
||||
|
@ -265,7 +265,7 @@ ossl_ocspreq_to_der(VALUE self)
|
|||
if((len = i2d_OCSP_REQUEST(req, NULL)) <= 0)
|
||||
ossl_raise(eOCSPError, NULL);
|
||||
str = rb_str_new(0, len);
|
||||
p = RSTRING(str)->ptr;
|
||||
p = RSTRING_PTR(str);
|
||||
if(i2d_OCSP_REQUEST(req, &p) <= 0)
|
||||
ossl_raise(eOCSPError, NULL);
|
||||
ossl_str_adjust(str, p);
|
||||
|
@ -316,9 +316,9 @@ ossl_ocspres_initialize(int argc, VALUE *argv, VALUE self)
|
|||
if(!NIL_P(arg)){
|
||||
arg = ossl_to_der_if_possible(arg);
|
||||
StringValue(arg);
|
||||
p = RSTRING(arg)->ptr;
|
||||
p = RSTRING_PTR(arg);
|
||||
if(!d2i_OCSP_RESPONSE((OCSP_RESPONSE**)&DATA_PTR(self), &p,
|
||||
RSTRING(arg)->len)){
|
||||
RSTRING_LEN(arg))){
|
||||
ossl_raise(eOCSPError, "cannot load DER encoded response");
|
||||
}
|
||||
}
|
||||
|
@ -377,7 +377,7 @@ ossl_ocspres_to_der(VALUE self)
|
|||
if((len = i2d_OCSP_RESPONSE(res, NULL)) <= 0)
|
||||
ossl_raise(eOCSPError, NULL);
|
||||
str = rb_str_new(0, len);
|
||||
p = RSTRING(str)->ptr;
|
||||
p = RSTRING_PTR(str);
|
||||
if(i2d_OCSP_RESPONSE(res, NULL) <= 0)
|
||||
ossl_raise(eOCSPError, NULL);
|
||||
ossl_str_adjust(str, p);
|
||||
|
@ -436,7 +436,7 @@ ossl_ocspbres_add_nonce(int argc, VALUE *argv, VALUE self)
|
|||
else{
|
||||
StringValue(val);
|
||||
GetOCSPBasicRes(self, bs);
|
||||
ret = OCSP_basic_add1_nonce(bs, RSTRING(val)->ptr, RSTRING(val)->len);
|
||||
ret = OCSP_basic_add1_nonce(bs, RSTRING_PTR(val), RSTRING_LEN(val));
|
||||
}
|
||||
if(!ret) ossl_raise(eOCSPError, NULL);
|
||||
|
||||
|
@ -461,8 +461,8 @@ ossl_ocspbres_add_status(VALUE self, VALUE cid, VALUE status,
|
|||
if(!NIL_P(ext)){
|
||||
/* All ary's members should be X509Extension */
|
||||
Check_Type(ext, T_ARRAY);
|
||||
for (i = 0; i < RARRAY(ext)->len; i++)
|
||||
OSSL_Check_Kind(RARRAY(ext)->ptr[i], cX509Ext);
|
||||
for (i = 0; i < RARRAY_LEN(ext); i++)
|
||||
OSSL_Check_Kind(RARRAY_PTR(ext)[i], cX509Ext);
|
||||
}
|
||||
|
||||
error = 0;
|
||||
|
@ -490,8 +490,8 @@ ossl_ocspbres_add_status(VALUE self, VALUE cid, VALUE status,
|
|||
X509_EXTENSION *x509ext;
|
||||
sk_X509_EXTENSION_pop_free(single->singleExtensions, X509_EXTENSION_free);
|
||||
single->singleExtensions = NULL;
|
||||
for(i = 0; i < RARRAY(ext)->len; i++){
|
||||
x509ext = DupX509ExtPtr(RARRAY(ext)->ptr[i]);
|
||||
for(i = 0; i < RARRAY_LEN(ext); i++){
|
||||
x509ext = DupX509ExtPtr(RARRAY_PTR(ext)[i]);
|
||||
if(!OCSP_SINGLERESP_add_ext(single, x509ext, -1)){
|
||||
X509_EXTENSION_free(x509ext);
|
||||
error = 1;
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
/*
|
||||
* Classes
|
||||
*/
|
||||
VALUE mPKCS12;
|
||||
VALUE cPKCS12;
|
||||
VALUE ePKCS12Error;
|
||||
|
||||
|
@ -49,32 +48,85 @@ ossl_pkcs12_s_allocate(VALUE klass)
|
|||
return obj;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* PKCS12.create(pass, name, key, cert [, ca, [, key_pbe [, cert_pbe [, key_iter [, mac_iter [, keytype]]]]]])
|
||||
*
|
||||
* === Parameters
|
||||
* * +pass+ - string
|
||||
* * +name+ - A string describing the key.
|
||||
* * +key+ - Any PKey.
|
||||
* * +cert+ - A X509::Certificate.
|
||||
* * * The public_key portion of the certificate must contain a valid public key.
|
||||
* * * The not_before and not_after fields must be filled in.
|
||||
* * +ca+ - An optional array of X509::Certificate's.
|
||||
* * +key_pbe+ - string
|
||||
* * +cert_pbe+ - string
|
||||
* * +key_iter+ - integer
|
||||
* * +mac_iter+ - integer
|
||||
* * +keytype+ - An integer representing an MSIE specific extension.
|
||||
*
|
||||
* Any optional arguments may be supplied as nil to preserve the OpenSSL defaults.
|
||||
*
|
||||
* See the OpenSSL documentation for PKCS12_create().
|
||||
*/
|
||||
static VALUE
|
||||
ossl_pkcs12_s_create(int argc, VALUE *argv, VALUE self)
|
||||
{
|
||||
VALUE pass, name, pkey, cert, ca;
|
||||
VALUE pass, name, pkey, cert, ca, key_nid, cert_nid, key_iter, mac_iter, keytype;
|
||||
VALUE obj;
|
||||
char *passphrase, *friendlyname;
|
||||
EVP_PKEY *key;
|
||||
X509 *x509;
|
||||
STACK_OF(X509) *x509s;
|
||||
int nkey = 0, ncert = 0, kiter = 0, miter = 0, ktype = 0;
|
||||
PKCS12 *p12;
|
||||
|
||||
rb_scan_args(argc, argv, "41", &pass, &name, &pkey, &cert, &ca);
|
||||
rb_scan_args(argc, argv, "46", &pass, &name, &pkey, &cert, &ca, &key_nid, &cert_nid, &key_iter, &mac_iter, &keytype);
|
||||
passphrase = NIL_P(pass) ? NULL : StringValuePtr(pass);
|
||||
friendlyname = NIL_P(name) ? NULL : StringValuePtr(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(StringValuePtr(key_nid))) == NID_undef)
|
||||
rb_raise(rb_eArgError, "Unknown PBE algorithm %s", StringValuePtr(key_nid));
|
||||
}
|
||||
if (!NIL_P(cert_nid)) {
|
||||
if ((ncert = OBJ_txt2nid(StringValuePtr(cert_nid))) == NID_undef)
|
||||
rb_raise(rb_eArgError, "Unknown PBE algorithm %s", StringValuePtr(cert_nid));
|
||||
}
|
||||
if (!NIL_P(key_iter))
|
||||
kiter = NUM2INT(key_iter);
|
||||
if (!NIL_P(mac_iter))
|
||||
miter = NUM2INT(mac_iter);
|
||||
if (!NIL_P(keytype))
|
||||
ktype = NUM2INT(keytype);
|
||||
|
||||
p12 = PKCS12_create(passphrase, friendlyname, key, x509, x509s,
|
||||
0, 0, 0, 0, 0);
|
||||
nkey, ncert, kiter, miter, ktype);
|
||||
sk_X509_pop_free(x509s, X509_free);
|
||||
if(!p12) ossl_raise(ePKCS12Error, NULL);
|
||||
WrapPKCS12(cPKCS12, obj, p12);
|
||||
|
||||
ossl_pkcs12_set_key(obj, pkey);
|
||||
ossl_pkcs12_set_cert(obj, cert);
|
||||
ossl_pkcs12_set_ca_certs(obj, ca);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* PKCS12.new -> pkcs12
|
||||
* PKCS12.new(str) -> pkcs12
|
||||
* PKCS12.new(str, pass) -> pkcs12
|
||||
*
|
||||
* === Parameters
|
||||
* * +str+ - Must be a DER encoded PKCS12 string.
|
||||
* * +pass+ - string
|
||||
*/
|
||||
static VALUE
|
||||
ossl_pkcs12_initialize(int argc, VALUE *argv, VALUE self)
|
||||
{
|
||||
|
@ -94,7 +146,7 @@ ossl_pkcs12_initialize(int argc, VALUE *argv, VALUE self)
|
|||
|
||||
pkey = cert = ca = Qnil;
|
||||
if(!PKCS12_parse((PKCS12*)DATA_PTR(self), passphrase, &key, &x509, &x509s))
|
||||
ossl_raise(ePKCS12Error, NULL);
|
||||
ossl_raise(ePKCS12Error, "PKCS12_parse");
|
||||
pkey = rb_protect((VALUE(*)_((VALUE)))ossl_pkey_new, (VALUE)key,
|
||||
&st); /* NO DUP */
|
||||
if(st) goto err;
|
||||
|
@ -129,7 +181,7 @@ ossl_pkcs12_to_der(VALUE self)
|
|||
if((len = i2d_PKCS12(p12, NULL)) <= 0)
|
||||
ossl_raise(ePKCS12Error, NULL);
|
||||
str = rb_str_new(0, len);
|
||||
p = RSTRING(str)->ptr;
|
||||
p = RSTRING_PTR(str);
|
||||
if(i2d_PKCS12(p12, &p) <= 0)
|
||||
ossl_raise(ePKCS12Error, NULL);
|
||||
ossl_str_adjust(str, p);
|
||||
|
@ -140,10 +192,14 @@ ossl_pkcs12_to_der(VALUE self)
|
|||
void
|
||||
Init_ossl_pkcs12()
|
||||
{
|
||||
mPKCS12 = rb_define_module_under(mOSSL, "PKCS12");
|
||||
cPKCS12 = rb_define_class_under(mPKCS12, "PKCS12", rb_cObject);
|
||||
ePKCS12Error = rb_define_class_under(mPKCS12, "PKCS12Error", eOSSLError);
|
||||
rb_define_module_function(mPKCS12, "create", ossl_pkcs12_s_create, -1);
|
||||
/*
|
||||
* Defines a file format commonly used to store private keys with
|
||||
* accompanying public key certificates, protected with a password-based
|
||||
* symmetric key.
|
||||
*/
|
||||
cPKCS12 = rb_define_class_under(mOSSL, "PKCS12", rb_cObject);
|
||||
ePKCS12Error = rb_define_class_under(cPKCS12, "PKCS12Error", eOSSLError);
|
||||
rb_define_singleton_method(cPKCS12, "create", ossl_pkcs12_s_create, -1);
|
||||
|
||||
rb_define_alloc_func(cPKCS12, ossl_pkcs12_s_allocate);
|
||||
rb_attr(cPKCS12, rb_intern("key"), 1, 0, Qfalse);
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
#if !defined(_OSSL_PKCS12_H_)
|
||||
#define _OSSL_PKCS12_H_
|
||||
|
||||
extern VALUE mPKCS12;
|
||||
extern VALUE cPKCS12;
|
||||
extern VALUE ePKCS12Error;
|
||||
|
||||
|
|
96
ext/openssl/ossl_pkcs5.c
Normal file
96
ext/openssl/ossl_pkcs5.c
Normal file
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
* $Id$
|
||||
* Copyright (C) 2007 Technorama Ltd. <oss-ruby@technorama.net>
|
||||
*/
|
||||
#include "ossl.h"
|
||||
|
||||
VALUE mPKCS5;
|
||||
VALUE ePKCS5;
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* PKCS5.pbkdf2_hmac(pass, salt, iter, keylen, digest) => string
|
||||
*
|
||||
* === Parameters
|
||||
* * +pass+ - string
|
||||
* * +salt+ - string
|
||||
* * +iter+ - integer - should be greater than 1000. 2000 is better.
|
||||
* * +keylen+ - integer
|
||||
* * +digest+ - a string or OpenSSL::Digest object.
|
||||
*
|
||||
* Available in OpenSSL 0.9.9?.
|
||||
*
|
||||
* Digests other than SHA1 may not be supported by other cryptography libraries.
|
||||
*/
|
||||
static VALUE
|
||||
ossl_pkcs5_pbkdf2_hmac(VALUE self, VALUE pass, VALUE salt, VALUE iter, VALUE keylen, VALUE digest)
|
||||
{
|
||||
#ifdef HAVE_PKCS5_PBKDF2_HMAC
|
||||
VALUE str;
|
||||
const EVP_MD md;
|
||||
int len = NUM2INT(keylen);
|
||||
|
||||
StringValue(pass);
|
||||
StringValue(salt);
|
||||
md = GetDigestPtr(digest);
|
||||
|
||||
str = rb_str_new(0, len);
|
||||
|
||||
if (PKCS5_PBKDF2_HMAC(RSTRING_PTR(pass), RSTRING_LEN(pass), RSTRING_PTR(salt), RSTRING_LEN(salt), NUM2INT(iter), md, len, RSTRING_PTR(str)) != 1)
|
||||
ossl_raise(ePKCS5, "PKCS5_PBKDF2_HMAC");
|
||||
|
||||
return str;
|
||||
#else
|
||||
rb_notimplement();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* PKCS5.pbkdf2_hmac_sha1(pass, salt, iter, keylen) => string
|
||||
*
|
||||
* === Parameters
|
||||
* * +pass+ - string
|
||||
* * +salt+ - string
|
||||
* * +iter+ - integer - should be greater than 1000. 2000 is better.
|
||||
* * +keylen+ - integer
|
||||
*
|
||||
* This method is available almost any version OpenSSL.
|
||||
*
|
||||
* Conforms to rfc2898.
|
||||
*/
|
||||
static VALUE
|
||||
ossl_pkcs5_pbkdf2_hmac_sha1(VALUE self, VALUE pass, VALUE salt, VALUE iter, VALUE keylen)
|
||||
{
|
||||
#ifdef HAVE_PKCS5_PBKDF2_HMAC_SHA1
|
||||
VALUE str;
|
||||
int len = NUM2INT(keylen);
|
||||
|
||||
StringValue(pass);
|
||||
StringValue(salt);
|
||||
|
||||
str = rb_str_new(0, len);
|
||||
|
||||
if (PKCS5_PBKDF2_HMAC_SHA1(RSTRING_PTR(pass), RSTRING_LEN(pass), RSTRING_PTR(salt), RSTRING_LEN(salt), NUM2INT(iter), len, RSTRING_PTR(str)) != 1)
|
||||
ossl_raise(ePKCS5, "PKCS5_PBKDF2_HMAC_SHA1");
|
||||
|
||||
return str;
|
||||
#else
|
||||
rb_notimplement();
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
Init_ossl_pkcs5()
|
||||
{
|
||||
/*
|
||||
* Password-based Encryption
|
||||
*
|
||||
*/
|
||||
mPKCS5 = rb_define_module_under(mOSSL, "PKCS5");
|
||||
ePKCS5 = rb_define_class_under(mPKCS5, "PKCS5Error", eOSSLError);
|
||||
|
||||
rb_define_module_function(mPKCS5, "pbkdf2_hmac", ossl_pkcs5_pbkdf2_hmac, 5);
|
||||
rb_define_module_function(mPKCS5, "pbkdf2_hmac_sha1", ossl_pkcs5_pbkdf2_hmac_sha1, 4);
|
||||
}
|
|
@ -71,7 +71,6 @@
|
|||
/*
|
||||
* Classes
|
||||
*/
|
||||
VALUE mPKCS7;
|
||||
VALUE cPKCS7;
|
||||
VALUE cPKCS7Signer;
|
||||
VALUE cPKCS7Recipient;
|
||||
|
@ -134,7 +133,8 @@ DupPKCS7RecipientPtr(VALUE obj)
|
|||
}
|
||||
|
||||
/*
|
||||
* Private
|
||||
* call-seq:
|
||||
* PKCS7.read_smime(string) => pkcs7
|
||||
*/
|
||||
static VALUE
|
||||
ossl_pkcs7_s_read_smime(VALUE klass, VALUE arg)
|
||||
|
@ -156,6 +156,10 @@ ossl_pkcs7_s_read_smime(VALUE klass, VALUE arg)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* PKCS7.write_smime(pkcs7 [, data [, flags]]) => string
|
||||
*/
|
||||
static VALUE
|
||||
ossl_pkcs7_s_write_smime(int argc, VALUE *argv, VALUE klass)
|
||||
{
|
||||
|
@ -187,6 +191,10 @@ ossl_pkcs7_s_write_smime(int argc, VALUE *argv, VALUE klass)
|
|||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* PKCS7.sign(cert, key, data, [, certs [, flags]]) => pkcs7
|
||||
*/
|
||||
static VALUE
|
||||
ossl_pkcs7_s_sign(int argc, VALUE *argv, VALUE klass)
|
||||
{
|
||||
|
@ -226,6 +234,10 @@ ossl_pkcs7_s_sign(int argc, VALUE *argv, VALUE klass)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* PKCS7.encrypt(certs, data, [, cipher [, flags]]) => pkcs7
|
||||
*/
|
||||
static VALUE
|
||||
ossl_pkcs7_s_encrypt(int argc, VALUE *argv, VALUE klass)
|
||||
{
|
||||
|
@ -287,6 +299,13 @@ ossl_pkcs7_alloc(VALUE klass)
|
|||
return obj;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* PKCS7.new => pkcs7
|
||||
* PKCS7.new(string) => pkcs7
|
||||
*
|
||||
* Many methods in this class aren't documented.
|
||||
*/
|
||||
static VALUE
|
||||
ossl_pkcs7_initialize(int argc, VALUE *argv, VALUE self)
|
||||
{
|
||||
|
@ -335,7 +354,7 @@ static int
|
|||
ossl_pkcs7_sym2typeid(VALUE sym)
|
||||
{
|
||||
int i, ret = Qnil;
|
||||
char *s;
|
||||
const char *s;
|
||||
|
||||
static struct {
|
||||
const char *name;
|
||||
|
@ -364,6 +383,10 @@ ossl_pkcs7_sym2typeid(VALUE sym)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* pkcs7.type = type => type
|
||||
*/
|
||||
static VALUE
|
||||
ossl_pkcs7_set_type(VALUE self, VALUE type)
|
||||
{
|
||||
|
@ -376,6 +399,10 @@ ossl_pkcs7_set_type(VALUE self, VALUE type)
|
|||
return type;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* pkcs7.type => string or nil
|
||||
*/
|
||||
static VALUE
|
||||
ossl_pkcs7_get_type(VALUE self)
|
||||
{
|
||||
|
@ -583,7 +610,7 @@ ossl_pkcs7_set_certificates(VALUE self, VALUE ary)
|
|||
|
||||
certs = pkcs7_get_certs_or_crls(self, 1);
|
||||
while((cert = sk_X509_pop(certs))) X509_free(cert);
|
||||
rb_iterate(rb_each, ary, ossl_pkcs7_set_certs_i, self);
|
||||
rb_block_call(ary, rb_intern("each"), 0, 0, ossl_pkcs7_set_certs_i, self);
|
||||
|
||||
return ary;
|
||||
}
|
||||
|
@ -623,7 +650,7 @@ ossl_pkcs7_set_crls(VALUE self, VALUE ary)
|
|||
|
||||
crls = pkcs7_get_certs_or_crls(self, 0);
|
||||
while((crl = sk_X509_CRL_pop(crls))) X509_CRL_free(crl);
|
||||
rb_iterate(rb_each, ary, ossl_pkcs7_set_crls_i, self);
|
||||
rb_block_call(ary, rb_intern("each"), 0, 0, ossl_pkcs7_set_crls_i, self);
|
||||
|
||||
return ary;
|
||||
}
|
||||
|
@ -751,7 +778,7 @@ ossl_pkcs7_to_der(VALUE self)
|
|||
if((len = i2d_PKCS7(pkcs7, NULL)) <= 0)
|
||||
ossl_raise(ePKCS7Error, NULL);
|
||||
str = rb_str_new(0, len);
|
||||
p = RSTRING(str)->ptr;
|
||||
p = RSTRING_PTR(str);
|
||||
if(i2d_PKCS7(pkcs7, &p) <= 0)
|
||||
ossl_raise(ePKCS7Error, NULL);
|
||||
ossl_str_adjust(str, p);
|
||||
|
@ -926,15 +953,12 @@ ossl_pkcs7ri_get_enc_key(VALUE self)
|
|||
void
|
||||
Init_ossl_pkcs7()
|
||||
{
|
||||
mPKCS7 = rb_define_module_under(mOSSL, "PKCS7");
|
||||
|
||||
ePKCS7Error = rb_define_class_under(mPKCS7, "PKCS7Error", eOSSLError);
|
||||
|
||||
cPKCS7 = rb_define_class_under(mPKCS7, "PKCS7", rb_cObject);
|
||||
rb_define_singleton_method(mPKCS7, "read_smime", ossl_pkcs7_s_read_smime, 1);
|
||||
rb_define_singleton_method(mPKCS7, "write_smime", ossl_pkcs7_s_write_smime, -1);
|
||||
rb_define_singleton_method(mPKCS7, "sign", ossl_pkcs7_s_sign, -1);
|
||||
rb_define_singleton_method(mPKCS7, "encrypt", ossl_pkcs7_s_encrypt, -1);
|
||||
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);
|
||||
rb_define_singleton_method(cPKCS7, "write_smime", ossl_pkcs7_s_write_smime, -1);
|
||||
rb_define_singleton_method(cPKCS7, "sign", ossl_pkcs7_s_sign, -1);
|
||||
rb_define_singleton_method(cPKCS7, "encrypt", ossl_pkcs7_s_encrypt, -1);
|
||||
rb_attr(cPKCS7, rb_intern("data"), 1, 0, Qfalse);
|
||||
rb_attr(cPKCS7, rb_intern("error_string"), 1, 1, Qfalse);
|
||||
rb_define_alloc_func(cPKCS7, ossl_pkcs7_alloc);
|
||||
|
@ -964,8 +988,8 @@ Init_ossl_pkcs7()
|
|||
rb_define_alias(cPKCS7, "to_s", "to_pem");
|
||||
rb_define_method(cPKCS7, "to_der", ossl_pkcs7_to_der, 0);
|
||||
|
||||
cPKCS7Signer = rb_define_class_under(mPKCS7, "SignerInfo", rb_cObject);
|
||||
rb_define_const(mPKCS7, "Signer", cPKCS7Signer);
|
||||
cPKCS7Signer = rb_define_class_under(cPKCS7, "SignerInfo", rb_cObject);
|
||||
rb_define_const(cPKCS7, "Signer", cPKCS7Signer);
|
||||
rb_define_alloc_func(cPKCS7Signer, ossl_pkcs7si_alloc);
|
||||
rb_define_method(cPKCS7Signer, "initialize", ossl_pkcs7si_initialize,3);
|
||||
rb_define_method(cPKCS7Signer, "issuer", ossl_pkcs7si_get_issuer, 0);
|
||||
|
@ -973,14 +997,14 @@ Init_ossl_pkcs7()
|
|||
rb_define_method(cPKCS7Signer, "serial", ossl_pkcs7si_get_serial,0);
|
||||
rb_define_method(cPKCS7Signer,"signed_time",ossl_pkcs7si_get_signed_time,0);
|
||||
|
||||
cPKCS7Recipient = rb_define_class_under(mPKCS7,"RecipientInfo",rb_cObject);
|
||||
cPKCS7Recipient = rb_define_class_under(cPKCS7,"RecipientInfo",rb_cObject);
|
||||
rb_define_alloc_func(cPKCS7Recipient, ossl_pkcs7ri_alloc);
|
||||
rb_define_method(cPKCS7Recipient, "initialize", ossl_pkcs7ri_initialize,1);
|
||||
rb_define_method(cPKCS7Recipient, "issuer", ossl_pkcs7ri_get_issuer,0);
|
||||
rb_define_method(cPKCS7Recipient, "serial", ossl_pkcs7ri_get_serial,0);
|
||||
rb_define_method(cPKCS7Recipient, "enc_key", ossl_pkcs7ri_get_enc_key,0);
|
||||
|
||||
#define DefPKCS7Const(x) rb_define_const(mPKCS7, #x, INT2NUM(PKCS7_##x))
|
||||
#define DefPKCS7Const(x) rb_define_const(cPKCS7, #x, INT2NUM(PKCS7_##x))
|
||||
|
||||
DefPKCS7Const(TEXT);
|
||||
DefPKCS7Const(NOCERTS);
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
#if !defined(_OSSL_PKCS7_H_)
|
||||
#define _OSSL_PKCS7_H_
|
||||
|
||||
extern VALUE mPKCS7;
|
||||
extern VALUE cPKCS7;
|
||||
extern VALUE cPKCS7Signer;
|
||||
extern VALUE cPKCS7Recipient;
|
||||
|
|
|
@ -54,6 +54,10 @@ ossl_pkey_new(EVP_PKEY *pkey)
|
|||
#if !defined(OPENSSL_NO_DH)
|
||||
case EVP_PKEY_DH:
|
||||
return ossl_dh_new(pkey);
|
||||
#endif
|
||||
#if !defined(OPENSSL_NO_EC) && (OPENSSL_VERSION_NUMBER >= 0x0090802fL)
|
||||
case EVP_PKEY_EC:
|
||||
return ossl_ec_new(pkey);
|
||||
#endif
|
||||
default:
|
||||
ossl_raise(ePKeyError, "unsupported key type");
|
||||
|
@ -68,7 +72,7 @@ ossl_pkey_new_from_file(VALUE filename)
|
|||
EVP_PKEY *pkey;
|
||||
|
||||
SafeStringValue(filename);
|
||||
if (!(fp = fopen(RSTRING(filename)->ptr, "r"))) {
|
||||
if (!(fp = fopen(RSTRING_PTR(filename), "r"))) {
|
||||
ossl_raise(ePKeyError, "%s", strerror(errno));
|
||||
}
|
||||
|
||||
|
@ -169,13 +173,12 @@ ossl_pkey_sign(VALUE self, VALUE digest, VALUE data)
|
|||
GetPKey(self, pkey);
|
||||
EVP_SignInit(&ctx, GetDigestPtr(digest));
|
||||
StringValue(data);
|
||||
EVP_SignUpdate(&ctx, RSTRING(data)->ptr, RSTRING(data)->len);
|
||||
EVP_SignUpdate(&ctx, RSTRING_PTR(data), RSTRING_LEN(data));
|
||||
str = rb_str_new(0, EVP_PKEY_size(pkey)+16);
|
||||
if (!EVP_SignFinal(&ctx, RSTRING(str)->ptr, &buf_len, pkey))
|
||||
if (!EVP_SignFinal(&ctx, RSTRING_PTR(str), &buf_len, pkey))
|
||||
ossl_raise(ePKeyError, NULL);
|
||||
assert(buf_len <= RSTRING(str)->len);
|
||||
RSTRING(str)->len = buf_len;
|
||||
RSTRING(str)->ptr[buf_len] = 0;
|
||||
assert(buf_len <= RSTRING_LEN(str));
|
||||
rb_str_set_len(str, buf_len);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
@ -190,8 +193,8 @@ ossl_pkey_verify(VALUE self, VALUE digest, VALUE sig, VALUE data)
|
|||
EVP_VerifyInit(&ctx, GetDigestPtr(digest));
|
||||
StringValue(sig);
|
||||
StringValue(data);
|
||||
EVP_VerifyUpdate(&ctx, RSTRING(data)->ptr, RSTRING(data)->len);
|
||||
switch (EVP_VerifyFinal(&ctx, RSTRING(sig)->ptr, RSTRING(sig)->len, pkey)) {
|
||||
EVP_VerifyUpdate(&ctx, RSTRING_PTR(data), RSTRING_LEN(data));
|
||||
switch (EVP_VerifyFinal(&ctx, RSTRING_PTR(sig), RSTRING_LEN(sig), pkey)) {
|
||||
case 0:
|
||||
return Qfalse;
|
||||
case 1:
|
||||
|
@ -227,10 +230,11 @@ Init_ossl_pkey()
|
|||
id_private_q = rb_intern("private?");
|
||||
|
||||
/*
|
||||
* INIT rsa, dsa
|
||||
* INIT rsa, dsa, dh, ec
|
||||
*/
|
||||
Init_ossl_rsa();
|
||||
Init_ossl_dsa();
|
||||
Init_ossl_dh();
|
||||
Init_ossl_ec();
|
||||
}
|
||||
|
||||
|
|
|
@ -77,7 +77,24 @@ extern DH *OSSL_DEFAULT_DH_1024;
|
|||
VALUE ossl_dh_new(EVP_PKEY *);
|
||||
void Init_ossl_dh(void);
|
||||
|
||||
/*
|
||||
* EC
|
||||
*/
|
||||
extern VALUE cEC;
|
||||
extern VALUE eECError;
|
||||
extern VALUE cEC_GROUP;
|
||||
extern VALUE eEC_GROUP;
|
||||
extern VALUE cEC_POINT;
|
||||
extern VALUE eEC_POINT;
|
||||
VALUE ossl_ec_new(EVP_PKEY *);
|
||||
void Init_ossl_ec(void);
|
||||
|
||||
|
||||
#define OSSL_PKEY_BN(keytype, name) \
|
||||
/* \
|
||||
* call-seq: \
|
||||
* key.##name -> aBN \
|
||||
*/ \
|
||||
static VALUE ossl_##keytype##_get_##name(VALUE self) \
|
||||
{ \
|
||||
EVP_PKEY *pkey; \
|
||||
|
@ -89,6 +106,10 @@ static VALUE ossl_##keytype##_get_##name(VALUE self) \
|
|||
return Qnil; \
|
||||
return ossl_bn_new(bn); \
|
||||
} \
|
||||
/* \
|
||||
* call-seq: \
|
||||
* key.##name = bn -> bn \
|
||||
*/ \
|
||||
static VALUE ossl_##keytype##_set_##name(VALUE self, VALUE bignum) \
|
||||
{ \
|
||||
EVP_PKEY *pkey; \
|
||||
|
|
|
@ -99,6 +99,15 @@ dh_generate(int size, int gen)
|
|||
return dh;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* DH.generate(size [, generator]) -> dh
|
||||
*
|
||||
* === Parameters
|
||||
* * +size+ is an integer representing the desired key size. Keys smaller than 1024 should be considered insecure.
|
||||
* * +generator+ is a small number > 1, typically 2 or 5.
|
||||
*
|
||||
*/
|
||||
static VALUE
|
||||
ossl_dh_s_generate(int argc, VALUE *argv, VALUE klass)
|
||||
{
|
||||
|
@ -119,6 +128,21 @@ ossl_dh_s_generate(int argc, VALUE *argv, VALUE klass)
|
|||
return obj;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* DH.new([size [, generator] | string]) -> dh
|
||||
*
|
||||
* === Parameters
|
||||
* * +size+ is an integer representing the desired key size. Keys smaller than 1024 should be considered insecure.
|
||||
* * +generator+ is a small number > 1, typically 2 or 5.
|
||||
* * +string+ contains the DER or PEM encoded key.
|
||||
*
|
||||
* === Examples
|
||||
* * DH.new -> dh
|
||||
* * DH.new(1024) -> dh
|
||||
* * DH.new(1024, 5) -> dh
|
||||
* * DH.new(File.read('key.pem')) -> dh
|
||||
*/
|
||||
static VALUE
|
||||
ossl_dh_initialize(int argc, VALUE *argv, VALUE self)
|
||||
{
|
||||
|
@ -158,19 +182,26 @@ ossl_dh_initialize(int argc, VALUE *argv, VALUE self)
|
|||
return self;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* dh.public? -> true | false
|
||||
*
|
||||
*/
|
||||
static VALUE
|
||||
ossl_dh_is_public(VALUE self)
|
||||
{
|
||||
EVP_PKEY *pkey;
|
||||
|
||||
GetPKeyDH(self, pkey);
|
||||
/*
|
||||
* Do we need to check dhp->dh->public_pkey?
|
||||
* return Qtrue;
|
||||
*/
|
||||
|
||||
return (pkey->pkey.dh->pub_key) ? Qtrue : Qfalse;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* dh.private? -> true | false
|
||||
*
|
||||
*/
|
||||
static VALUE
|
||||
ossl_dh_is_private(VALUE self)
|
||||
{
|
||||
|
@ -181,6 +212,11 @@ ossl_dh_is_private(VALUE self)
|
|||
return (DH_PRIVATE(pkey->pkey.dh)) ? Qtrue : Qfalse;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* dh.to_pem -> aString
|
||||
*
|
||||
*/
|
||||
static VALUE
|
||||
ossl_dh_export(VALUE self)
|
||||
{
|
||||
|
@ -201,6 +237,11 @@ ossl_dh_export(VALUE self)
|
|||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* dh.to_der -> aString
|
||||
*
|
||||
*/
|
||||
static VALUE
|
||||
ossl_dh_to_der(VALUE self)
|
||||
{
|
||||
|
@ -213,7 +254,7 @@ ossl_dh_to_der(VALUE self)
|
|||
if((len = i2d_DHparams(pkey->pkey.dh, NULL)) <= 0)
|
||||
ossl_raise(eDHError, NULL);
|
||||
str = rb_str_new(0, len);
|
||||
p = RSTRING(str)->ptr;
|
||||
p = RSTRING_PTR(str);
|
||||
if(i2d_DHparams(pkey->pkey.dh, &p) < 0)
|
||||
ossl_raise(eDHError, NULL);
|
||||
ossl_str_adjust(str, p);
|
||||
|
@ -222,6 +263,9 @@ ossl_dh_to_der(VALUE self)
|
|||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* dh.params -> hash
|
||||
*
|
||||
* Stores all parameters of key to the hash
|
||||
* INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!!
|
||||
* Don't use :-)) (I's up to you)
|
||||
|
@ -245,6 +289,9 @@ ossl_dh_get_params(VALUE self)
|
|||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* dh.to_text -> aString
|
||||
*
|
||||
* Prints all parameters of key to buffer
|
||||
* INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!!
|
||||
* Don't use :-)) (I's up to you)
|
||||
|
@ -270,6 +317,9 @@ ossl_dh_to_text(VALUE self)
|
|||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* dh.public_key -> aDH
|
||||
*
|
||||
* Makes new instance DH PUBLIC_KEY from PRIVATE_KEY
|
||||
*/
|
||||
static VALUE
|
||||
|
@ -290,6 +340,11 @@ ossl_dh_to_public_key(VALUE self)
|
|||
return obj;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* dh.check_params -> true | false
|
||||
*
|
||||
*/
|
||||
static VALUE
|
||||
ossl_dh_check_params(VALUE self)
|
||||
{
|
||||
|
@ -307,6 +362,11 @@ ossl_dh_check_params(VALUE self)
|
|||
return codes == 0 ? Qtrue : Qfalse;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* dh.generate_key -> self
|
||||
*
|
||||
*/
|
||||
static VALUE
|
||||
ossl_dh_generate_key(VALUE self)
|
||||
{
|
||||
|
@ -321,6 +381,18 @@ ossl_dh_generate_key(VALUE self)
|
|||
return self;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* dh.compute_key(pub_bn) -> aString
|
||||
*
|
||||
* === Parameters
|
||||
* * +pub_bn+ is a OpenSSL::BN.
|
||||
*
|
||||
* Returns aString containing a shared secret computed from the other parties public value.
|
||||
*
|
||||
* See DH_compute_key() for further information.
|
||||
*
|
||||
*/
|
||||
static VALUE
|
||||
ossl_dh_compute_key(VALUE self, VALUE pub)
|
||||
{
|
||||
|
@ -335,11 +407,10 @@ ossl_dh_compute_key(VALUE self, VALUE pub)
|
|||
pub_key = GetBNPtr(pub);
|
||||
len = DH_size(dh);
|
||||
str = rb_str_new(0, len);
|
||||
if ((len = DH_compute_key(RSTRING(str)->ptr, pub_key, dh)) < 0) {
|
||||
if ((len = DH_compute_key(RSTRING_PTR(str), pub_key, dh)) < 0) {
|
||||
ossl_raise(eDHError, NULL);
|
||||
}
|
||||
RSTRING(str)->len = len;
|
||||
RSTRING(str)->ptr[len] = 0;
|
||||
rb_str_set_len(str, len);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
|
|
@ -99,6 +99,14 @@ dsa_generate(int size)
|
|||
return dsa;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* DSA.generate(size) -> dsa
|
||||
*
|
||||
* === Parameters
|
||||
* * +size+ is an integer representing the desired key size.
|
||||
*
|
||||
*/
|
||||
static VALUE
|
||||
ossl_dsa_s_generate(VALUE klass, VALUE size)
|
||||
{
|
||||
|
@ -113,6 +121,22 @@ ossl_dsa_s_generate(VALUE klass, VALUE size)
|
|||
return obj;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* DSA.new([size | string [, pass]) -> dsa
|
||||
*
|
||||
* === Parameters
|
||||
* * +size+ is an integer representing the desired key size.
|
||||
* * +string+ contains a DER or PEM encoded key.
|
||||
* * +pass+ is a string that contains a optional password.
|
||||
*
|
||||
* === Examples
|
||||
* * DSA.new -> dsa
|
||||
* * DSA.new(1024) -> dsa
|
||||
* * DSA.new(File.read('dsa.pem')) -> dsa
|
||||
* * DSA.new(File.read('dsa.pem'), 'mypassword') -> dsa
|
||||
*
|
||||
*/
|
||||
static VALUE
|
||||
ossl_dsa_initialize(int argc, VALUE *argv, VALUE self)
|
||||
{
|
||||
|
@ -163,6 +187,11 @@ ossl_dsa_initialize(int argc, VALUE *argv, VALUE self)
|
|||
return self;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* dsa.public? -> true | false
|
||||
*
|
||||
*/
|
||||
static VALUE
|
||||
ossl_dsa_is_public(VALUE self)
|
||||
{
|
||||
|
@ -170,13 +199,14 @@ ossl_dsa_is_public(VALUE self)
|
|||
|
||||
GetPKeyDSA(self, pkey);
|
||||
|
||||
/*
|
||||
* Do we need to check dsap->dsa->public_pkey?
|
||||
* return Qtrue;
|
||||
*/
|
||||
return (pkey->pkey.dsa->pub_key) ? Qtrue : Qfalse;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* dsa.private? -> true | false
|
||||
*
|
||||
*/
|
||||
static VALUE
|
||||
ossl_dsa_is_private(VALUE self)
|
||||
{
|
||||
|
@ -187,6 +217,19 @@ ossl_dsa_is_private(VALUE self)
|
|||
return (DSA_PRIVATE(self, pkey->pkey.dsa)) ? Qtrue : Qfalse;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* dsa.to_pem([cipher, password]) -> aString
|
||||
*
|
||||
* === Parameters
|
||||
* +cipher+ is an OpenSSL::Cipher.
|
||||
* +password+ is a string containing your password.
|
||||
*
|
||||
* === Examples
|
||||
* * DSA.to_pem -> aString
|
||||
* * DSA.to_pem(cipher, 'mypassword') -> aString
|
||||
*
|
||||
*/
|
||||
static VALUE
|
||||
ossl_dsa_export(int argc, VALUE *argv, VALUE self)
|
||||
{
|
||||
|
@ -224,6 +267,11 @@ ossl_dsa_export(int argc, VALUE *argv, VALUE self)
|
|||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* dsa.to_der -> aString
|
||||
*
|
||||
*/
|
||||
static VALUE
|
||||
ossl_dsa_to_der(VALUE self)
|
||||
{
|
||||
|
@ -241,7 +289,7 @@ ossl_dsa_to_der(VALUE self)
|
|||
if((len = i2d_func(pkey->pkey.dsa, NULL)) <= 0)
|
||||
ossl_raise(eDSAError, NULL);
|
||||
str = rb_str_new(0, len);
|
||||
p = RSTRING(str)->ptr;
|
||||
p = RSTRING_PTR(str);
|
||||
if(i2d_func(pkey->pkey.dsa, &p) < 0)
|
||||
ossl_raise(eDSAError, NULL);
|
||||
ossl_str_adjust(str, p);
|
||||
|
@ -250,6 +298,9 @@ ossl_dsa_to_der(VALUE self)
|
|||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* dsa.params -> hash
|
||||
*
|
||||
* Stores all parameters of key to the hash
|
||||
* INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!!
|
||||
* Don't use :-)) (I's up to you)
|
||||
|
@ -274,6 +325,9 @@ ossl_dsa_get_params(VALUE self)
|
|||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* dsa.to_text -> aString
|
||||
*
|
||||
* Prints all parameters of key to buffer
|
||||
* INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!!
|
||||
* Don't use :-)) (I's up to you)
|
||||
|
@ -299,6 +353,9 @@ ossl_dsa_to_text(VALUE self)
|
|||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* dsa.public_key -> aDSA
|
||||
*
|
||||
* Makes new instance DSA PUBLIC_KEY from PRIVATE_KEY
|
||||
*/
|
||||
static VALUE
|
||||
|
@ -321,6 +378,11 @@ ossl_dsa_to_public_key(VALUE self)
|
|||
|
||||
#define ossl_dsa_buf_size(pkey) (DSA_size((pkey)->pkey.dsa)+16)
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* dsa.syssign(string) -> aString
|
||||
*
|
||||
*/
|
||||
static VALUE
|
||||
ossl_dsa_sign(VALUE self, VALUE data)
|
||||
{
|
||||
|
@ -334,16 +396,20 @@ ossl_dsa_sign(VALUE self, VALUE data)
|
|||
ossl_raise(eDSAError, "Private DSA key needed!");
|
||||
}
|
||||
str = rb_str_new(0, ossl_dsa_buf_size(pkey));
|
||||
if (!DSA_sign(0, RSTRING(data)->ptr, RSTRING(data)->len, RSTRING(str)->ptr,
|
||||
if (!DSA_sign(0, RSTRING_PTR(data), RSTRING_LEN(data), RSTRING_PTR(str),
|
||||
&buf_len, pkey->pkey.dsa)) { /* type is ignored (0) */
|
||||
ossl_raise(eDSAError, NULL);
|
||||
}
|
||||
RSTRING(str)->len = buf_len;
|
||||
RSTRING(str)->ptr[buf_len] = 0;
|
||||
rb_str_set_len(str, buf_len);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* dsa.sysverify(digest, sig) -> true | false
|
||||
*
|
||||
*/
|
||||
static VALUE
|
||||
ossl_dsa_verify(VALUE self, VALUE digest, VALUE sig)
|
||||
{
|
||||
|
@ -354,8 +420,8 @@ ossl_dsa_verify(VALUE self, VALUE digest, VALUE sig)
|
|||
StringValue(digest);
|
||||
StringValue(sig);
|
||||
/* type is ignored (0) */
|
||||
ret = DSA_verify(0, RSTRING(digest)->ptr, RSTRING(digest)->len,
|
||||
RSTRING(sig)->ptr, RSTRING(sig)->len, pkey->pkey.dsa);
|
||||
ret = DSA_verify(0, RSTRING_PTR(digest), RSTRING_LEN(digest),
|
||||
RSTRING_PTR(sig), RSTRING_LEN(sig), pkey->pkey.dsa);
|
||||
if (ret < 0) {
|
||||
ossl_raise(eDSAError, NULL);
|
||||
}
|
||||
|
|
1438
ext/openssl/ossl_pkey_ec.c
Normal file
1438
ext/openssl/ossl_pkey_ec.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -84,9 +84,19 @@ rsa_generate(int size, int exp)
|
|||
NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* RSA.generate(size [, exponent]) -> rsa
|
||||
*
|
||||
* === Parameters
|
||||
* * +size+ is an integer representing the desired key size. Keys smaller than 1024 should be considered insecure.
|
||||
* * +exponent+ is an odd number normally 3, 17, or 65537.
|
||||
*
|
||||
*/
|
||||
static VALUE
|
||||
ossl_rsa_s_generate(int argc, VALUE *argv, VALUE klass)
|
||||
{
|
||||
/* why does this method exist? why can't initialize take an optional exponent? */
|
||||
RSA *rsa;
|
||||
VALUE size, exp;
|
||||
VALUE obj;
|
||||
|
@ -104,6 +114,20 @@ ossl_rsa_s_generate(int argc, VALUE *argv, VALUE klass)
|
|||
return obj;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* RSA.new([size | encoded_key] [, pass]) -> rsa
|
||||
*
|
||||
* === Parameters
|
||||
* * +size+ is an integer representing the desired key size.
|
||||
* * +encoded_key+ is a string containing PEM or DER encoded key.
|
||||
* * +pass+ is an optional string with the password to decrypt the encoded key.
|
||||
*
|
||||
* === Examples
|
||||
* * RSA.new(2048) -> rsa
|
||||
* * RSA.new(File.read("rsa.pem")) -> rsa
|
||||
* * RSA.new(File.read("rsa.pem"), "mypassword") -> rsa
|
||||
*/
|
||||
static VALUE
|
||||
ossl_rsa_initialize(int argc, VALUE *argv, VALUE self)
|
||||
{
|
||||
|
@ -157,6 +181,13 @@ ossl_rsa_initialize(int argc, VALUE *argv, VALUE self)
|
|||
return self;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* rsa.public? -> true
|
||||
*
|
||||
* The return value is always true since every private key is also a public key.
|
||||
*
|
||||
*/
|
||||
static VALUE
|
||||
ossl_rsa_is_public(VALUE self)
|
||||
{
|
||||
|
@ -164,12 +195,16 @@ ossl_rsa_is_public(VALUE self)
|
|||
|
||||
GetPKeyRSA(self, pkey);
|
||||
/*
|
||||
* SURPRISE! :-))
|
||||
* Every key is public at the same time!
|
||||
* This method should check for n and e. BUG.
|
||||
*/
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* rsa.private? -> true | false
|
||||
*
|
||||
*/
|
||||
static VALUE
|
||||
ossl_rsa_is_private(VALUE self)
|
||||
{
|
||||
|
@ -180,6 +215,18 @@ ossl_rsa_is_private(VALUE self)
|
|||
return (RSA_PRIVATE(self, pkey->pkey.rsa)) ? Qtrue : Qfalse;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* rsa.to_pem([cipher, pass]) -> aString
|
||||
*
|
||||
* === Parameters
|
||||
* * +cipher+ is a Cipher object.
|
||||
* * +pass+ is a string.
|
||||
*
|
||||
* === Examples
|
||||
* * rsa.to_pem -> aString
|
||||
* * rsa.to_pem(cipher, pass) -> aString
|
||||
*/
|
||||
static VALUE
|
||||
ossl_rsa_export(int argc, VALUE *argv, VALUE self)
|
||||
{
|
||||
|
@ -219,6 +266,11 @@ ossl_rsa_export(int argc, VALUE *argv, VALUE self)
|
|||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* rsa.to_der -> aString
|
||||
*
|
||||
*/
|
||||
static VALUE
|
||||
ossl_rsa_to_der(VALUE self)
|
||||
{
|
||||
|
@ -236,7 +288,7 @@ ossl_rsa_to_der(VALUE self)
|
|||
if((len = i2d_func(pkey->pkey.rsa, NULL)) <= 0)
|
||||
ossl_raise(eRSAError, NULL);
|
||||
str = rb_str_new(0, len);
|
||||
p = RSTRING(str)->ptr;
|
||||
p = RSTRING_PTR(str);
|
||||
if(i2d_func(pkey->pkey.rsa, &p) < 0)
|
||||
ossl_raise(eRSAError, NULL);
|
||||
ossl_str_adjust(str, p);
|
||||
|
@ -246,6 +298,11 @@ ossl_rsa_to_der(VALUE self)
|
|||
|
||||
#define ossl_rsa_buf_size(pkey) (RSA_size((pkey)->pkey.rsa)+16)
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* rsa.public_encrypt(string [, padding]) -> aString
|
||||
*
|
||||
*/
|
||||
static VALUE
|
||||
ossl_rsa_public_encrypt(int argc, VALUE *argv, VALUE self)
|
||||
{
|
||||
|
@ -258,16 +315,20 @@ ossl_rsa_public_encrypt(int argc, VALUE *argv, VALUE self)
|
|||
pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding);
|
||||
StringValue(buffer);
|
||||
str = rb_str_new(0, ossl_rsa_buf_size(pkey));
|
||||
buf_len = RSA_public_encrypt(RSTRING(buffer)->len, RSTRING(buffer)->ptr,
|
||||
RSTRING(str)->ptr, pkey->pkey.rsa,
|
||||
buf_len = RSA_public_encrypt(RSTRING_LEN(buffer), RSTRING_PTR(buffer),
|
||||
RSTRING_PTR(str), pkey->pkey.rsa,
|
||||
pad);
|
||||
if (buf_len < 0) ossl_raise(eRSAError, NULL);
|
||||
RSTRING(str)->len = buf_len;
|
||||
RSTRING(str)->ptr[buf_len] = 0;
|
||||
rb_str_set_len(str, buf_len);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* rsa.public_decrypt(string [, padding]) -> aString
|
||||
*
|
||||
*/
|
||||
static VALUE
|
||||
ossl_rsa_public_decrypt(int argc, VALUE *argv, VALUE self)
|
||||
{
|
||||
|
@ -280,16 +341,20 @@ ossl_rsa_public_decrypt(int argc, VALUE *argv, VALUE self)
|
|||
pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding);
|
||||
StringValue(buffer);
|
||||
str = rb_str_new(0, ossl_rsa_buf_size(pkey));
|
||||
buf_len = RSA_public_decrypt(RSTRING(buffer)->len, RSTRING(buffer)->ptr,
|
||||
RSTRING(str)->ptr, pkey->pkey.rsa,
|
||||
buf_len = RSA_public_decrypt(RSTRING_LEN(buffer), RSTRING_PTR(buffer),
|
||||
RSTRING_PTR(str), pkey->pkey.rsa,
|
||||
pad);
|
||||
if (buf_len < 0) ossl_raise(eRSAError, NULL);
|
||||
RSTRING(str)->len = buf_len;
|
||||
RSTRING(str)->ptr[buf_len] = 0;
|
||||
rb_str_set_len(str, buf_len);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* rsa.private_encrypt(string [, padding]) -> aString
|
||||
*
|
||||
*/
|
||||
static VALUE
|
||||
ossl_rsa_private_encrypt(int argc, VALUE *argv, VALUE self)
|
||||
{
|
||||
|
@ -305,16 +370,21 @@ ossl_rsa_private_encrypt(int argc, VALUE *argv, VALUE self)
|
|||
pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding);
|
||||
StringValue(buffer);
|
||||
str = rb_str_new(0, ossl_rsa_buf_size(pkey));
|
||||
buf_len = RSA_private_encrypt(RSTRING(buffer)->len, RSTRING(buffer)->ptr,
|
||||
RSTRING(str)->ptr, pkey->pkey.rsa,
|
||||
buf_len = RSA_private_encrypt(RSTRING_LEN(buffer), RSTRING_PTR(buffer),
|
||||
RSTRING_PTR(str), pkey->pkey.rsa,
|
||||
pad);
|
||||
if (buf_len < 0) ossl_raise(eRSAError, NULL);
|
||||
RSTRING(str)->len = buf_len;
|
||||
RSTRING(str)->ptr[buf_len] = 0;
|
||||
rb_str_set_len(str, buf_len);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* rsa.private_decrypt(string [, padding]) -> aString
|
||||
*
|
||||
*/
|
||||
static VALUE
|
||||
ossl_rsa_private_decrypt(int argc, VALUE *argv, VALUE self)
|
||||
{
|
||||
|
@ -330,17 +400,19 @@ ossl_rsa_private_decrypt(int argc, VALUE *argv, VALUE self)
|
|||
pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding);
|
||||
StringValue(buffer);
|
||||
str = rb_str_new(0, ossl_rsa_buf_size(pkey));
|
||||
buf_len = RSA_private_decrypt(RSTRING(buffer)->len, RSTRING(buffer)->ptr,
|
||||
RSTRING(str)->ptr, pkey->pkey.rsa,
|
||||
buf_len = RSA_private_decrypt(RSTRING_LEN(buffer), RSTRING_PTR(buffer),
|
||||
RSTRING_PTR(str), pkey->pkey.rsa,
|
||||
pad);
|
||||
if (buf_len < 0) ossl_raise(eRSAError, NULL);
|
||||
RSTRING(str)->len = buf_len;
|
||||
RSTRING(str)->ptr[buf_len] = 0;
|
||||
rb_str_set_len(str, buf_len);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* rsa.params -> hash
|
||||
*
|
||||
* Stores all parameters of key to the hash
|
||||
* INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!!
|
||||
* Don't use :-)) (I's up to you)
|
||||
|
@ -368,6 +440,9 @@ ossl_rsa_get_params(VALUE self)
|
|||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* rsa.to_text -> aString
|
||||
*
|
||||
* Prints all parameters of key to buffer
|
||||
* INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!!
|
||||
* Don't use :-)) (It's up to you)
|
||||
|
@ -393,6 +468,9 @@ ossl_rsa_to_text(VALUE self)
|
|||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* rsa.public_key -> aRSA
|
||||
*
|
||||
* Makes new instance RSA PUBLIC_KEY from PRIVATE_KEY
|
||||
*/
|
||||
static VALUE
|
||||
|
@ -415,7 +493,6 @@ ossl_rsa_to_public_key(VALUE self)
|
|||
|
||||
/*
|
||||
* TODO: Test me
|
||||
extern BN_CTX *ossl_bn_ctx;
|
||||
|
||||
static VALUE
|
||||
ossl_rsa_blinding_on(VALUE self)
|
||||
|
|
|
@ -31,75 +31,105 @@ static VALUE
|
|||
ossl_rand_seed(VALUE self, VALUE str)
|
||||
{
|
||||
StringValue(str);
|
||||
RAND_seed(RSTRING(str)->ptr, RSTRING(str)->len);
|
||||
RAND_seed(RSTRING_PTR(str), RSTRING_LEN(str));
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* load_random_file(filename) -> true
|
||||
*
|
||||
*/
|
||||
static VALUE
|
||||
ossl_rand_load_file(VALUE self, VALUE filename)
|
||||
{
|
||||
SafeStringValue(filename);
|
||||
|
||||
if(!RAND_load_file(RSTRING(filename)->ptr, -1)) {
|
||||
if(!RAND_load_file(RSTRING_PTR(filename), -1)) {
|
||||
ossl_raise(eRandomError, NULL);
|
||||
}
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* write_random_file(filename) -> true
|
||||
*
|
||||
*/
|
||||
static VALUE
|
||||
ossl_rand_write_file(VALUE self, VALUE filename)
|
||||
{
|
||||
SafeStringValue(filename);
|
||||
if (RAND_write_file(RSTRING(filename)->ptr) == -1) {
|
||||
if (RAND_write_file(RSTRING_PTR(filename)) == -1) {
|
||||
ossl_raise(eRandomError, NULL);
|
||||
}
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* random_bytes(length) -> aString
|
||||
*
|
||||
*/
|
||||
static VALUE
|
||||
ossl_rand_bytes(VALUE self, VALUE len)
|
||||
{
|
||||
VALUE str;
|
||||
|
||||
str = rb_str_new(0, FIX2INT(len));
|
||||
if (!RAND_bytes(RSTRING(str)->ptr, FIX2INT(len))) {
|
||||
if (!RAND_bytes(RSTRING_PTR(str), FIX2INT(len))) {
|
||||
ossl_raise(eRandomError, NULL);
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* pseudo_bytes(length) -> aString
|
||||
*
|
||||
*/
|
||||
static VALUE
|
||||
ossl_rand_pseudo_bytes(VALUE self, VALUE len)
|
||||
{
|
||||
VALUE str;
|
||||
|
||||
str = rb_str_new(0, FIX2INT(len));
|
||||
if (!RAND_pseudo_bytes(RSTRING(str)->ptr, FIX2INT(len))) {
|
||||
if (!RAND_pseudo_bytes(RSTRING_PTR(str), FIX2INT(len))) {
|
||||
ossl_raise(eRandomError, NULL);
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* egd(filename) -> true
|
||||
*
|
||||
*/
|
||||
static VALUE
|
||||
ossl_rand_egd(VALUE self, VALUE filename)
|
||||
{
|
||||
SafeStringValue(filename);
|
||||
|
||||
if(!RAND_egd(RSTRING(filename)->ptr)) {
|
||||
if(!RAND_egd(RSTRING_PTR(filename))) {
|
||||
ossl_raise(eRandomError, NULL);
|
||||
}
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* egd_bytes(filename, length) -> true
|
||||
*
|
||||
*/
|
||||
static VALUE
|
||||
ossl_rand_egd_bytes(VALUE self, VALUE filename, VALUE len)
|
||||
{
|
||||
SafeStringValue(filename);
|
||||
|
||||
if (!RAND_egd_bytes(RSTRING(filename)->ptr, FIX2INT(len))) {
|
||||
if (!RAND_egd_bytes(RSTRING_PTR(filename), FIX2INT(len))) {
|
||||
ossl_raise(eRandomError, NULL);
|
||||
}
|
||||
return Qtrue;
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
* 'OpenSSL for Ruby' project
|
||||
* Copyright (C) 2000-2002 GOTOU Yuuzou <gotoyuzo@notwork.org>
|
||||
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
|
||||
* Copyright (C) 2001-2007 Technorama Ltd. <oss-ruby@technorama.net>
|
||||
* All rights reserved.
|
||||
*/
|
||||
/*
|
||||
|
@ -30,9 +31,6 @@ VALUE eSSLError;
|
|||
VALUE cSSLContext;
|
||||
VALUE cSSLSocket;
|
||||
|
||||
/*
|
||||
* SSLContext class
|
||||
*/
|
||||
#define ossl_sslctx_set_cert(o,v) rb_iv_set((o),"@cert",(v))
|
||||
#define ossl_sslctx_set_key(o,v) rb_iv_set((o),"@key",(v))
|
||||
#define ossl_sslctx_set_client_ca(o,v) rb_iv_set((o),"@client_ca",(v))
|
||||
|
@ -65,11 +63,12 @@ VALUE cSSLSocket;
|
|||
#define ossl_sslctx_get_tmp_dh_cb(o) rb_iv_get((o),"@tmp_dh_callback")
|
||||
#define ossl_sslctx_get_sess_id_ctx(o) rb_iv_get((o),"@session_id_context")
|
||||
|
||||
static char *ossl_sslctx_attrs[] = {
|
||||
static const char *ossl_sslctx_attrs[] = {
|
||||
"cert", "key", "client_ca", "ca_file", "ca_path",
|
||||
"timeout", "verify_mode", "verify_depth",
|
||||
"verify_callback", "options", "cert_store", "extra_chain_cert",
|
||||
"client_cert_cb", "tmp_dh_callback", "session_id_context",
|
||||
"session_get_cb", "session_new_cb", "session_remove_cb",
|
||||
};
|
||||
|
||||
#define ossl_ssl_get_io(o) rb_iv_get((o),"@io")
|
||||
|
@ -86,8 +85,10 @@ static char *ossl_sslctx_attrs[] = {
|
|||
#define ossl_ssl_set_key(o,v) rb_iv_set((o),"@key",(v))
|
||||
#define ossl_ssl_set_tmp_dh(o,v) rb_iv_set((o),"@tmp_dh",(v))
|
||||
|
||||
static char *ossl_ssl_attr_readers[] = { "io", "context", };
|
||||
static char *ossl_ssl_attrs[] = { "sync_close", };
|
||||
static const char *ossl_ssl_attr_readers[] = { "io", "context", };
|
||||
static const char *ossl_ssl_attrs[] = { "sync_close", };
|
||||
|
||||
ID ID_callback_state;
|
||||
|
||||
/*
|
||||
* SSLContext class
|
||||
|
@ -140,6 +141,14 @@ ossl_sslctx_s_alloc(VALUE klass)
|
|||
return Data_Wrap_Struct(klass, 0, ossl_sslctx_free, ctx);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* SSLContext.new => ctx
|
||||
* SSLContext.new(:TLSv1) => ctx
|
||||
* SSLContext.new("SSLv23_client") => ctx
|
||||
*
|
||||
* You can get a list of valid methods with OpenSSL::SSL::SSLContext::METHODS
|
||||
*/
|
||||
static VALUE
|
||||
ossl_sslctx_initialize(int argc, VALUE *argv, VALUE self)
|
||||
{
|
||||
|
@ -147,7 +156,7 @@ ossl_sslctx_initialize(int argc, VALUE *argv, VALUE self)
|
|||
SSL_METHOD *method = NULL;
|
||||
SSL_CTX *ctx;
|
||||
int i;
|
||||
char *s;
|
||||
const char *s;
|
||||
|
||||
for(i = 0; i < numberof(ossl_sslctx_attrs); i++){
|
||||
char buf[32];
|
||||
|
@ -273,6 +282,143 @@ ossl_ssl_verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
|
|||
return ossl_verify_cb(preverify_ok, ctx);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
ossl_call_session_get_cb(VALUE ary)
|
||||
{
|
||||
VALUE ssl_obj, sslctx_obj, cb, ret;
|
||||
|
||||
Check_Type(ary, T_ARRAY);
|
||||
ssl_obj = rb_ary_entry(ary, 0);
|
||||
|
||||
sslctx_obj = rb_iv_get(ssl_obj, "@context");
|
||||
if (NIL_P(sslctx_obj)) return Qnil;
|
||||
cb = rb_iv_get(sslctx_obj, "@session_get_cb");
|
||||
if (NIL_P(cb)) return Qnil;
|
||||
|
||||
return rb_funcall(cb, rb_intern("call"), 1, ary);
|
||||
}
|
||||
|
||||
/* this method is currently only called for servers (in OpenSSL <= 0.9.8e) */
|
||||
static SSL_SESSION *
|
||||
ossl_sslctx_session_get_cb(SSL *ssl, unsigned char *buf, int len, int *copy)
|
||||
{
|
||||
VALUE ary, ssl_obj, ret_obj;
|
||||
SSL_SESSION *sess;
|
||||
void *ptr;
|
||||
int state = 0;
|
||||
|
||||
OSSL_Debug("SSL SESSION get callback entered");
|
||||
if ((ptr = SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx)) == NULL)
|
||||
return NULL;
|
||||
ssl_obj = (VALUE)ptr;
|
||||
ary = rb_ary_new2(2);
|
||||
rb_ary_push(ary, ssl_obj);
|
||||
rb_ary_push(ary, rb_str_new(buf, len));
|
||||
|
||||
ret_obj = rb_protect((VALUE(*)_((VALUE)))ossl_call_session_get_cb, ary, &state);
|
||||
if (state) {
|
||||
rb_ivar_set(ssl_obj, ID_callback_state, INT2NUM(state));
|
||||
return NULL;
|
||||
}
|
||||
if (!rb_obj_is_instance_of(ret_obj, cSSLSession))
|
||||
return NULL;
|
||||
|
||||
SafeGetSSLSession(ret_obj, sess);
|
||||
*copy = 1;
|
||||
|
||||
return sess;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
ossl_call_session_new_cb(VALUE ary)
|
||||
{
|
||||
VALUE ssl_obj, sslctx_obj, cb, ret;
|
||||
|
||||
Check_Type(ary, T_ARRAY);
|
||||
ssl_obj = rb_ary_entry(ary, 0);
|
||||
|
||||
sslctx_obj = rb_iv_get(ssl_obj, "@context");
|
||||
if (NIL_P(sslctx_obj)) return Qnil;
|
||||
cb = rb_iv_get(sslctx_obj, "@session_new_cb");
|
||||
if (NIL_P(cb)) return Qnil;
|
||||
|
||||
return rb_funcall(cb, rb_intern("call"), 1, ary);
|
||||
}
|
||||
|
||||
/* return 1 normal. return 0 removes the session */
|
||||
static int
|
||||
ossl_sslctx_session_new_cb(SSL *ssl, SSL_SESSION *sess)
|
||||
{
|
||||
VALUE ary, ssl_obj, sess_obj, ret_obj;
|
||||
void *ptr;
|
||||
int state = 0;
|
||||
|
||||
OSSL_Debug("SSL SESSION new callback entered");
|
||||
|
||||
if ((ptr = SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx)) == NULL)
|
||||
return 1;
|
||||
ssl_obj = (VALUE)ptr;
|
||||
sess_obj = rb_obj_alloc(cSSLSession);
|
||||
CRYPTO_add(&sess->references, 1, CRYPTO_LOCK_SSL_SESSION);
|
||||
DATA_PTR(sess_obj) = sess;
|
||||
|
||||
ary = rb_ary_new2(2);
|
||||
rb_ary_push(ary, ssl_obj);
|
||||
rb_ary_push(ary, sess_obj);
|
||||
|
||||
ret_obj = rb_protect((VALUE(*)_((VALUE)))ossl_call_session_new_cb, ary, &state);
|
||||
if (state) {
|
||||
rb_ivar_set(ssl_obj, ID_callback_state, INT2NUM(state));
|
||||
return 0; /* what should be returned here??? */
|
||||
}
|
||||
|
||||
return RTEST(ret_obj) ? 1 : 0;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
ossl_call_session_remove_cb(VALUE ary)
|
||||
{
|
||||
VALUE sslctx_obj, cb, ret;
|
||||
|
||||
Check_Type(ary, T_ARRAY);
|
||||
sslctx_obj = rb_ary_entry(ary, 0);
|
||||
|
||||
cb = rb_iv_get(sslctx_obj, "@session_remove_cb");
|
||||
if (NIL_P(cb)) return Qnil;
|
||||
|
||||
return rb_funcall(cb, rb_intern("call"), 1, ary);
|
||||
}
|
||||
|
||||
static void
|
||||
ossl_sslctx_session_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess)
|
||||
{
|
||||
VALUE ary, sslctx_obj, sess_obj, ret_obj;
|
||||
void *ptr;
|
||||
int state = 0;
|
||||
|
||||
OSSL_Debug("SSL SESSION remove callback entered");
|
||||
|
||||
if ((ptr = SSL_CTX_get_ex_data(ctx, ossl_ssl_ex_ptr_idx)) == NULL)
|
||||
return;
|
||||
sslctx_obj = (VALUE)ptr;
|
||||
sess_obj = rb_obj_alloc(cSSLSession);
|
||||
CRYPTO_add(&sess->references, 1, CRYPTO_LOCK_SSL_SESSION);
|
||||
DATA_PTR(sess_obj) = sess;
|
||||
|
||||
ary = rb_ary_new2(2);
|
||||
rb_ary_push(ary, sslctx_obj);
|
||||
rb_ary_push(ary, sess_obj);
|
||||
|
||||
ret_obj = rb_protect((VALUE(*)_((VALUE)))ossl_call_session_new_cb, ary, &state);
|
||||
if (state) {
|
||||
/*
|
||||
the SSL_CTX is frozen, nowhere to save state.
|
||||
there is no common accessor method to check it either.
|
||||
rb_ivar_set(sslctx_obj, ID_callback_state, INT2NUM(state));
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
static VALUE
|
||||
ossl_sslctx_add_extra_chain_cert_i(VALUE i, VALUE arg)
|
||||
{
|
||||
|
@ -311,6 +457,7 @@ ossl_sslctx_setup(VALUE self)
|
|||
SSL_CTX_set_tmp_dh_callback(ctx, ossl_default_tmp_dh_callback);
|
||||
}
|
||||
#endif
|
||||
SSL_CTX_set_ex_data(ctx, ossl_ssl_ex_ptr_idx, (void*)self);
|
||||
|
||||
val = ossl_sslctx_get_cert_store(self);
|
||||
if(!NIL_P(val)){
|
||||
|
@ -327,7 +474,7 @@ ossl_sslctx_setup(VALUE self)
|
|||
|
||||
val = ossl_sslctx_get_extra_cert(self);
|
||||
if(!NIL_P(val)){
|
||||
rb_iterate(rb_each, val, ossl_sslctx_add_extra_chain_cert_i, self);
|
||||
rb_block_call(val, rb_intern("each"), 0, 0, ossl_sslctx_add_extra_chain_cert_i, self);
|
||||
}
|
||||
|
||||
/* private key may be bundled in certificate file. */
|
||||
|
@ -352,8 +499,8 @@ ossl_sslctx_setup(VALUE self)
|
|||
val = ossl_sslctx_get_client_ca(self);
|
||||
if(!NIL_P(val)){
|
||||
if(TYPE(val) == T_ARRAY){
|
||||
for(i = 0; i < RARRAY(val)->len; i++){
|
||||
client_ca = GetX509CertPtr(RARRAY(val)->ptr[i]);
|
||||
for(i = 0; i < RARRAY_LEN(val); i++){
|
||||
client_ca = GetX509CertPtr(RARRAY_PTR(val)[i]);
|
||||
if (!SSL_CTX_add_client_CA(ctx, client_ca)){
|
||||
/* Copies X509_NAME => FREE it. */
|
||||
ossl_raise(eSSLError, "SSL_CTX_add_client_CA");
|
||||
|
@ -397,12 +544,24 @@ ossl_sslctx_setup(VALUE self)
|
|||
val = ossl_sslctx_get_sess_id_ctx(self);
|
||||
if (!NIL_P(val)){
|
||||
StringValue(val);
|
||||
if (!SSL_CTX_set_session_id_context(ctx, RSTRING(val)->ptr,
|
||||
RSTRING(val)->len)){
|
||||
if (!SSL_CTX_set_session_id_context(ctx, RSTRING_PTR(val),
|
||||
RSTRING_LEN(val))){
|
||||
ossl_raise(eSSLError, "SSL_CTX_set_session_id_context:");
|
||||
}
|
||||
}
|
||||
|
||||
if (RTEST(rb_iv_get(self, "@session_get_cb"))) {
|
||||
SSL_CTX_sess_set_get_cb(ctx, ossl_sslctx_session_get_cb);
|
||||
OSSL_Debug("SSL SESSION get callback added");
|
||||
}
|
||||
if (RTEST(rb_iv_get(self, "@session_new_cb"))) {
|
||||
SSL_CTX_sess_set_new_cb(ctx, ossl_sslctx_session_new_cb);
|
||||
OSSL_Debug("SSL SESSION new callback added");
|
||||
}
|
||||
if (RTEST(rb_iv_get(self, "@session_remove_cb"))) {
|
||||
SSL_CTX_sess_set_remove_cb(ctx, ossl_sslctx_session_remove_cb);
|
||||
OSSL_Debug("SSL SESSION remove callback added");
|
||||
}
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
|
@ -422,6 +581,10 @@ ossl_ssl_cipher_to_ary(SSL_CIPHER *cipher)
|
|||
return ary;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* ctx.ciphers => [[name, version, bits, alg_bits], ...]
|
||||
*/
|
||||
static VALUE
|
||||
ossl_sslctx_get_ciphers(VALUE self)
|
||||
{
|
||||
|
@ -450,6 +613,12 @@ ossl_sslctx_get_ciphers(VALUE self)
|
|||
return ary;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* ctx.ciphers = "cipher1:cipher2:..."
|
||||
* ctx.ciphers = [name, ...]
|
||||
* ctx.ciphers = [[name, version, bits, alg_bits], ...]
|
||||
*/
|
||||
static VALUE
|
||||
ossl_sslctx_set_ciphers(VALUE self, VALUE v)
|
||||
{
|
||||
|
@ -462,12 +631,12 @@ ossl_sslctx_set_ciphers(VALUE self, VALUE v)
|
|||
return v;
|
||||
else if (TYPE(v) == T_ARRAY) {
|
||||
str = rb_str_new(0, 0);
|
||||
for (i = 0; i < RARRAY(v)->len; i++) {
|
||||
for (i = 0; i < RARRAY_LEN(v); i++) {
|
||||
elem = rb_ary_entry(v, i);
|
||||
if (TYPE(elem) == T_ARRAY) elem = rb_ary_entry(elem, 0);
|
||||
elem = rb_String(elem);
|
||||
rb_str_append(str, elem);
|
||||
if (i < RARRAY(v)->len-1) rb_str_cat2(str, ":");
|
||||
if (i < RARRAY_LEN(v)-1) rb_str_cat2(str, ":");
|
||||
}
|
||||
} else {
|
||||
str = v;
|
||||
|
@ -479,13 +648,173 @@ ossl_sslctx_set_ciphers(VALUE self, VALUE v)
|
|||
ossl_raise(eSSLError, "SSL_CTX is not initialized.");
|
||||
return Qnil;
|
||||
}
|
||||
if (!SSL_CTX_set_cipher_list(ctx, RSTRING(str)->ptr)) {
|
||||
if (!SSL_CTX_set_cipher_list(ctx, RSTRING_PTR(str))) {
|
||||
ossl_raise(eSSLError, "SSL_CTX_set_cipher_list:");
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* ctx.session_add(session) -> true | false
|
||||
*
|
||||
*/
|
||||
static VALUE
|
||||
ossl_sslctx_session_add(VALUE self, VALUE arg)
|
||||
{
|
||||
SSL_CTX *ctx;
|
||||
SSL_SESSION *sess;
|
||||
|
||||
Data_Get_Struct(self, SSL_CTX, ctx);
|
||||
SafeGetSSLSession(arg, sess);
|
||||
|
||||
return SSL_CTX_add_session(ctx, sess) == 1 ? Qtrue : Qfalse;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* ctx.session_remove(session) -> true | false
|
||||
*
|
||||
*/
|
||||
static VALUE
|
||||
ossl_sslctx_session_remove(VALUE self, VALUE arg)
|
||||
{
|
||||
SSL_CTX *ctx;
|
||||
SSL_SESSION *sess;
|
||||
|
||||
Data_Get_Struct(self, SSL_CTX, ctx);
|
||||
SafeGetSSLSession(arg, sess);
|
||||
|
||||
return SSL_CTX_remove_session(ctx, sess) == 1 ? Qtrue : Qfalse;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* ctx.session_cache_mode -> integer
|
||||
*
|
||||
*/
|
||||
static VALUE
|
||||
ossl_sslctx_get_session_cache_mode(VALUE self)
|
||||
{
|
||||
SSL_CTX *ctx;
|
||||
|
||||
Data_Get_Struct(self, SSL_CTX, ctx);
|
||||
|
||||
return LONG2NUM(SSL_CTX_get_session_cache_mode(ctx));
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* ctx.session_cache_mode=(integer) -> integer
|
||||
*
|
||||
*/
|
||||
static VALUE
|
||||
ossl_sslctx_set_session_cache_mode(VALUE self, VALUE arg)
|
||||
{
|
||||
SSL_CTX *ctx;
|
||||
|
||||
Data_Get_Struct(self, SSL_CTX, ctx);
|
||||
|
||||
SSL_CTX_set_session_cache_mode(ctx, NUM2LONG(arg));
|
||||
|
||||
return arg;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* ctx.session_cache_size -> integer
|
||||
*
|
||||
*/
|
||||
static VALUE
|
||||
ossl_sslctx_get_session_cache_size(VALUE self)
|
||||
{
|
||||
SSL_CTX *ctx;
|
||||
|
||||
Data_Get_Struct(self, SSL_CTX, ctx);
|
||||
|
||||
return LONG2NUM(SSL_CTX_sess_get_cache_size(ctx));
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* ctx.session_cache_size=(integer) -> integer
|
||||
*
|
||||
*/
|
||||
static VALUE
|
||||
ossl_sslctx_set_session_cache_size(VALUE self, VALUE arg)
|
||||
{
|
||||
SSL_CTX *ctx;
|
||||
|
||||
Data_Get_Struct(self, SSL_CTX, ctx);
|
||||
|
||||
SSL_CTX_sess_set_cache_size(ctx, NUM2LONG(arg));
|
||||
|
||||
return arg;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* ctx.session_cache_stats -> Hash
|
||||
*
|
||||
*/
|
||||
static VALUE
|
||||
ossl_sslctx_get_session_cache_stats(VALUE self)
|
||||
{
|
||||
SSL_CTX *ctx;
|
||||
VALUE hash;
|
||||
|
||||
Data_Get_Struct(self, SSL_CTX, ctx);
|
||||
|
||||
hash = rb_hash_new();
|
||||
rb_hash_aset(hash, rb_str_new2("cache_num"), LONG2NUM(SSL_CTX_sess_number(ctx)));
|
||||
rb_hash_aset(hash, rb_str_new2("connect"), LONG2NUM(SSL_CTX_sess_connect(ctx)));
|
||||
rb_hash_aset(hash, rb_str_new2("connect_good"), LONG2NUM(SSL_CTX_sess_connect_good(ctx)));
|
||||
rb_hash_aset(hash, rb_str_new2("connect_renegotiate"), LONG2NUM(SSL_CTX_sess_connect_renegotiate(ctx)));
|
||||
rb_hash_aset(hash, rb_str_new2("accept"), LONG2NUM(SSL_CTX_sess_accept(ctx)));
|
||||
rb_hash_aset(hash, rb_str_new2("accept_good"), LONG2NUM(SSL_CTX_sess_accept_good(ctx)));
|
||||
rb_hash_aset(hash, rb_str_new2("accept_renegotiate"), LONG2NUM(SSL_CTX_sess_accept_renegotiate(ctx)));
|
||||
rb_hash_aset(hash, rb_str_new2("cache_hits"), LONG2NUM(SSL_CTX_sess_hits(ctx)));
|
||||
rb_hash_aset(hash, rb_str_new2("cb_hits"), LONG2NUM(SSL_CTX_sess_cb_hits(ctx)));
|
||||
rb_hash_aset(hash, rb_str_new2("cache_misses"), LONG2NUM(SSL_CTX_sess_misses(ctx)));
|
||||
rb_hash_aset(hash, rb_str_new2("cache_full"), LONG2NUM(SSL_CTX_sess_cache_full(ctx)));
|
||||
rb_hash_aset(hash, rb_str_new2("timeouts"), LONG2NUM(SSL_CTX_sess_timeouts(ctx)));
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* ctx.flush_sessions(time | nil) -> self
|
||||
*
|
||||
*/
|
||||
static VALUE
|
||||
ossl_sslctx_flush_sessions(int argc, VALUE *argv, VALUE self)
|
||||
{
|
||||
VALUE arg1;
|
||||
SSL_CTX *ctx;
|
||||
time_t tm = 0;
|
||||
int cb_state;
|
||||
|
||||
rb_scan_args(argc, argv, "01", &arg1);
|
||||
|
||||
Data_Get_Struct(self, SSL_CTX, ctx);
|
||||
|
||||
if (NIL_P(arg1)) {
|
||||
tm = time(0);
|
||||
} else if (rb_obj_is_instance_of(arg1, rb_cTime)) {
|
||||
tm = NUM2LONG(rb_funcall(arg1, rb_intern("to_i"), 0));
|
||||
} else {
|
||||
rb_raise(rb_eArgError, "arg must be Time or nil");
|
||||
}
|
||||
|
||||
SSL_CTX_flush_sessions(ctx, tm);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
/*
|
||||
* SSLSocket class
|
||||
*/
|
||||
|
@ -511,6 +840,20 @@ ossl_ssl_s_alloc(VALUE klass)
|
|||
return Data_Wrap_Struct(klass, 0, ossl_ssl_free, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* SSLSocket.new(io) => aSSLSocket
|
||||
* SSLSocket.new(io, ctx) => aSSLSocket
|
||||
*
|
||||
* === Parameters
|
||||
* * +io+ is a real ruby IO object. Not an IO like object that responds to read/write.
|
||||
* * +ctx+ is an OpenSSLSSL::SSLContext.
|
||||
*
|
||||
* The OpenSSL::Buffering module provides additional IO methods.
|
||||
*
|
||||
* This method will freeze the SSLContext if one is provided;
|
||||
* however, session management is still allowed in the frozen SSLContext.
|
||||
*/
|
||||
static VALUE
|
||||
ossl_ssl_initialize(int argc, VALUE *argv, VALUE self)
|
||||
{
|
||||
|
@ -536,7 +879,7 @@ ossl_ssl_setup(VALUE self)
|
|||
VALUE io, v_ctx, cb;
|
||||
SSL_CTX *ctx;
|
||||
SSL *ssl;
|
||||
OpenFile *fptr;
|
||||
rb_io_t *fptr;
|
||||
|
||||
Data_Get_Struct(self, SSL, ssl);
|
||||
if(!ssl){
|
||||
|
@ -553,7 +896,7 @@ ossl_ssl_setup(VALUE self)
|
|||
GetOpenFile(io, fptr);
|
||||
rb_io_check_readable(fptr);
|
||||
rb_io_check_writable(fptr);
|
||||
SSL_set_fd(ssl, TO_SOCKET(fileno(fptr->f)));
|
||||
SSL_set_fd(ssl, TO_SOCKET(FPTR_TO_FD(fptr)));
|
||||
SSL_set_ex_data(ssl, ossl_ssl_ex_ptr_idx, (void*)self);
|
||||
cb = ossl_sslctx_get_verify_cb(v_ctx);
|
||||
SSL_set_ex_data(ssl, ossl_ssl_ex_vcb_idx, (void*)cb);
|
||||
|
@ -567,61 +910,85 @@ ossl_ssl_setup(VALUE self)
|
|||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
#define ssl_get_error(ssl, ret) \
|
||||
(errno = WSAGetLastError(), SSL_get_error(ssl, ret))
|
||||
#define ssl_get_error(ssl, ret) (errno = WSAGetLastError(), SSL_get_error(ssl, ret))
|
||||
#else
|
||||
#define ssl_get_error(ssl, ret) SSL_get_error(ssl, ret)
|
||||
#endif
|
||||
|
||||
static VALUE
|
||||
ossl_start_ssl(VALUE self, int (*func)())
|
||||
ossl_start_ssl(VALUE self, int (*func)(), const char *funcname)
|
||||
{
|
||||
SSL *ssl;
|
||||
OpenFile *fptr;
|
||||
int ret;
|
||||
rb_io_t *fptr;
|
||||
int ret, ret2;
|
||||
VALUE cb_state;
|
||||
|
||||
rb_ivar_set(self, ID_callback_state, Qnil);
|
||||
|
||||
Data_Get_Struct(self, SSL, ssl);
|
||||
GetOpenFile(ossl_ssl_get_io(self), fptr);
|
||||
for(;;){
|
||||
if((ret = func(ssl)) > 0) break;
|
||||
switch(ssl_get_error(ssl, ret)){
|
||||
switch((ret2 = ssl_get_error(ssl, ret))){
|
||||
case SSL_ERROR_WANT_WRITE:
|
||||
rb_io_wait_writable(fileno(fptr->f));
|
||||
rb_io_wait_writable(FPTR_TO_FD(fptr));
|
||||
continue;
|
||||
case SSL_ERROR_WANT_READ:
|
||||
rb_io_wait_readable(fileno(fptr->f));
|
||||
rb_io_wait_readable(FPTR_TO_FD(fptr));
|
||||
continue;
|
||||
case SSL_ERROR_SYSCALL:
|
||||
if (errno) rb_sys_fail(0);
|
||||
if (errno) rb_sys_fail(funcname);
|
||||
ossl_raise(eSSLError, "%s SYSCALL returned=%d errno=%d state=%s", funcname, ret2, errno, SSL_state_string_long(ssl));
|
||||
default:
|
||||
ossl_raise(eSSLError, NULL);
|
||||
ossl_raise(eSSLError, "%s returned=%d errno=%d state=%s", funcname, ret2, errno, SSL_state_string_long(ssl));
|
||||
}
|
||||
}
|
||||
|
||||
cb_state = rb_ivar_get(self, ID_callback_state);
|
||||
if (!NIL_P(cb_state))
|
||||
rb_jump_tag(NUM2INT(cb_state));
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* ssl.connect => self
|
||||
*/
|
||||
static VALUE
|
||||
ossl_ssl_connect(VALUE self)
|
||||
{
|
||||
ossl_ssl_setup(self);
|
||||
return ossl_start_ssl(self, SSL_connect);
|
||||
return ossl_start_ssl(self, SSL_connect, "SSL_connect");
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* ssl.accept => self
|
||||
*/
|
||||
static VALUE
|
||||
ossl_ssl_accept(VALUE self)
|
||||
{
|
||||
ossl_ssl_setup(self);
|
||||
return ossl_start_ssl(self, SSL_accept);
|
||||
return ossl_start_ssl(self, SSL_accept, "SSL_accept");
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* ssl.sysread(length) => string
|
||||
* ssl.sysread(length, buffer) => buffer
|
||||
*
|
||||
* === Parameters
|
||||
* * +length+ is a positive integer.
|
||||
* * +buffer+ is a string used to store the result.
|
||||
*/
|
||||
static VALUE
|
||||
ossl_ssl_read(int argc, VALUE *argv, VALUE self)
|
||||
{
|
||||
SSL *ssl;
|
||||
int ilen, nread = 0;
|
||||
VALUE len, str;
|
||||
OpenFile *fptr;
|
||||
rb_io_t *fptr;
|
||||
|
||||
rb_scan_args(argc, argv, "11", &len, &str);
|
||||
ilen = NUM2INT(len);
|
||||
|
@ -637,19 +1004,19 @@ ossl_ssl_read(int argc, VALUE *argv, VALUE self)
|
|||
GetOpenFile(ossl_ssl_get_io(self), fptr);
|
||||
if (ssl) {
|
||||
if(SSL_pending(ssl) <= 0)
|
||||
rb_thread_wait_fd(fileno(fptr->f));
|
||||
rb_thread_wait_fd(FPTR_TO_FD(fptr));
|
||||
for (;;){
|
||||
nread = SSL_read(ssl, RSTRING(str)->ptr, RSTRING(str)->len);
|
||||
nread = SSL_read(ssl, RSTRING_PTR(str), RSTRING_LEN(str));
|
||||
switch(ssl_get_error(ssl, nread)){
|
||||
case SSL_ERROR_NONE:
|
||||
goto end;
|
||||
case SSL_ERROR_ZERO_RETURN:
|
||||
rb_eof_error();
|
||||
case SSL_ERROR_WANT_WRITE:
|
||||
rb_io_wait_writable(fileno(fptr->f));
|
||||
rb_io_wait_writable(FPTR_TO_FD(fptr));
|
||||
continue;
|
||||
case SSL_ERROR_WANT_READ:
|
||||
rb_io_wait_readable(fileno(fptr->f));
|
||||
rb_io_wait_readable(FPTR_TO_FD(fptr));
|
||||
continue;
|
||||
case SSL_ERROR_SYSCALL:
|
||||
if(ERR_peek_error() == 0 && nread == 0) rb_eof_error();
|
||||
|
@ -666,19 +1033,22 @@ ossl_ssl_read(int argc, VALUE *argv, VALUE self)
|
|||
}
|
||||
|
||||
end:
|
||||
RSTRING(str)->len = nread;
|
||||
RSTRING(str)->ptr[nread] = 0;
|
||||
rb_str_set_len(str, nread);
|
||||
OBJ_TAINT(str);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* ssl.syswrite(string) => integer
|
||||
*/
|
||||
static VALUE
|
||||
ossl_ssl_write(VALUE self, VALUE str)
|
||||
{
|
||||
SSL *ssl;
|
||||
int nwrite = 0;
|
||||
OpenFile *fptr;
|
||||
rb_io_t *fptr;
|
||||
|
||||
StringValue(str);
|
||||
Data_Get_Struct(self, SSL, ssl);
|
||||
|
@ -686,15 +1056,15 @@ ossl_ssl_write(VALUE self, VALUE str)
|
|||
|
||||
if (ssl) {
|
||||
for (;;){
|
||||
nwrite = SSL_write(ssl, RSTRING(str)->ptr, RSTRING(str)->len);
|
||||
nwrite = SSL_write(ssl, RSTRING_PTR(str), RSTRING_LEN(str));
|
||||
switch(ssl_get_error(ssl, nwrite)){
|
||||
case SSL_ERROR_NONE:
|
||||
goto end;
|
||||
case SSL_ERROR_WANT_WRITE:
|
||||
rb_io_wait_writable(fileno(fptr->f));
|
||||
rb_io_wait_writable(FPTR_TO_FD(fptr));
|
||||
continue;
|
||||
case SSL_ERROR_WANT_READ:
|
||||
rb_io_wait_readable(fileno(fptr->f));
|
||||
rb_io_wait_readable(FPTR_TO_FD(fptr));
|
||||
continue;
|
||||
case SSL_ERROR_SYSCALL:
|
||||
if (errno) rb_sys_fail(0);
|
||||
|
@ -713,6 +1083,10 @@ ossl_ssl_write(VALUE self, VALUE str)
|
|||
return INT2NUM(nwrite);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* ssl.sysclose => nil
|
||||
*/
|
||||
static VALUE
|
||||
ossl_ssl_close(VALUE self)
|
||||
{
|
||||
|
@ -726,6 +1100,10 @@ ossl_ssl_close(VALUE self)
|
|||
return Qnil;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* ssl.cert => cert or nil
|
||||
*/
|
||||
static VALUE
|
||||
ossl_ssl_get_cert(VALUE self)
|
||||
{
|
||||
|
@ -750,6 +1128,10 @@ ossl_ssl_get_cert(VALUE self)
|
|||
return ossl_x509_new(cert);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* ssl.peer_cert => cert or nil
|
||||
*/
|
||||
static VALUE
|
||||
ossl_ssl_get_peer_cert(VALUE self)
|
||||
{
|
||||
|
@ -775,6 +1157,10 @@ ossl_ssl_get_peer_cert(VALUE self)
|
|||
return obj;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* ssl.peer_cert_chain => [cert, ...] or nil
|
||||
*/
|
||||
static VALUE
|
||||
ossl_ssl_get_peer_cert_chain(VALUE self)
|
||||
{
|
||||
|
@ -801,6 +1187,10 @@ ossl_ssl_get_peer_cert_chain(VALUE self)
|
|||
return ary;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* ssl.cipher => [name, version, bits, alg_bits]
|
||||
*/
|
||||
static VALUE
|
||||
ossl_ssl_get_cipher(VALUE self)
|
||||
{
|
||||
|
@ -817,6 +1207,10 @@ ossl_ssl_get_cipher(VALUE self)
|
|||
return ossl_ssl_cipher_to_ary(cipher);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* ssl.state => string
|
||||
*/
|
||||
static VALUE
|
||||
ossl_ssl_get_state(VALUE self)
|
||||
{
|
||||
|
@ -836,6 +1230,10 @@ ossl_ssl_get_state(VALUE self)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* ssl.pending => integer
|
||||
*/
|
||||
static VALUE
|
||||
ossl_ssl_pending(VALUE self)
|
||||
{
|
||||
|
@ -850,15 +1248,70 @@ ossl_ssl_pending(VALUE self)
|
|||
return INT2NUM(SSL_pending(ssl));
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* ssl.session_reused? -> true | false
|
||||
*
|
||||
*/
|
||||
static VALUE
|
||||
ossl_ssl_session_reused(VALUE self)
|
||||
{
|
||||
SSL *ssl;
|
||||
|
||||
Data_Get_Struct(self, SSL, ssl);
|
||||
if (!ssl) {
|
||||
rb_warning("SSL session is not started yet.");
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
switch(SSL_session_reused(ssl)) {
|
||||
case 1: return Qtrue;
|
||||
case 0: return Qfalse;
|
||||
default: ossl_raise(eSSLError, "SSL_session_reused");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* ssl.session = session -> session
|
||||
*
|
||||
*/
|
||||
static VALUE
|
||||
ossl_ssl_set_session(VALUE self, VALUE arg1)
|
||||
{
|
||||
SSL *ssl;
|
||||
SSL_SESSION *sess;
|
||||
|
||||
/* why is ossl_ssl_setup delayed? */
|
||||
ossl_ssl_setup(self);
|
||||
|
||||
Data_Get_Struct(self, SSL, ssl);
|
||||
if (!ssl) {
|
||||
rb_warning("SSL session is not started yet.");
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
SafeGetSSLSession(arg1, sess);
|
||||
|
||||
if (SSL_set_session(ssl, sess) != 1)
|
||||
ossl_raise(eSSLError, "SSL_set_session");
|
||||
|
||||
return arg1;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Init_ossl_ssl()
|
||||
{
|
||||
int i;
|
||||
VALUE ary;
|
||||
|
||||
#if 0 /* let rdoc know about mOSSL */
|
||||
mOSSL = rb_define_module("OpenSSL");
|
||||
#endif
|
||||
|
||||
ID_callback_state = rb_intern("@callback_state");
|
||||
|
||||
ossl_ssl_ex_vcb_idx = SSL_get_ex_new_index(0,"ossl_ssl_ex_vcb_idx",0,0,0);
|
||||
ossl_ssl_ex_store_p = SSL_get_ex_new_index(0,"ossl_ssl_ex_store_p",0,0,0);
|
||||
ossl_ssl_ex_ptr_idx = SSL_get_ex_new_index(0,"ossl_ssl_ex_ptr_idx",0,0,0);
|
||||
|
@ -870,7 +1323,14 @@ Init_ossl_ssl()
|
|||
mSSL = rb_define_module_under(mOSSL, "SSL");
|
||||
eSSLError = rb_define_class_under(mSSL, "SSLError", eOSSLError);
|
||||
|
||||
/* class SSLContext */
|
||||
/* class SSLContext
|
||||
*
|
||||
* The following attributes are available but don't show up in rdoc.
|
||||
* All attributes must be set before calling SSLSocket.new(io, ctx).
|
||||
* * cert, key, client_ca, ca_file, ca_path, timeout, verify_mode, verify_depth
|
||||
* * client_cert_cb, tmp_dh_callback, session_id_context,
|
||||
* * session_add_cb, session_new_cb, session_remove_cb
|
||||
*/
|
||||
cSSLContext = rb_define_class_under(mSSL, "SSLContext", rb_cObject);
|
||||
rb_define_alloc_func(cSSLContext, ossl_sslctx_s_alloc);
|
||||
for(i = 0; i < numberof(ossl_sslctx_attrs); i++)
|
||||
|
@ -879,7 +1339,38 @@ Init_ossl_ssl()
|
|||
rb_define_method(cSSLContext, "ciphers", ossl_sslctx_get_ciphers, 0);
|
||||
rb_define_method(cSSLContext, "ciphers=", ossl_sslctx_set_ciphers, 1);
|
||||
|
||||
/* class SSLSocket */
|
||||
|
||||
rb_define_const(cSSLContext, "SESSION_CACHE_OFF", LONG2FIX(SSL_SESS_CACHE_OFF));
|
||||
rb_define_const(cSSLContext, "SESSION_CACHE_CLIENT", LONG2FIX(SSL_SESS_CACHE_CLIENT)); /* doesn't actually do anything in 0.9.8e */
|
||||
rb_define_const(cSSLContext, "SESSION_CACHE_SERVER", LONG2FIX(SSL_SESS_CACHE_SERVER));
|
||||
rb_define_const(cSSLContext, "SESSION_CACHE_BOTH", LONG2FIX(SSL_SESS_CACHE_BOTH)); /* no different than CACHE_SERVER in 0.9.8e */
|
||||
rb_define_const(cSSLContext, "SESSION_CACHE_NO_AUTO_CLEAR", LONG2FIX(SSL_SESS_CACHE_NO_AUTO_CLEAR));
|
||||
rb_define_const(cSSLContext, "SESSION_CACHE_NO_INTERNAL_LOOKUP", LONG2FIX(SSL_SESS_CACHE_NO_INTERNAL_LOOKUP));
|
||||
rb_define_const(cSSLContext, "SESSION_CACHE_NO_INTERNAL_STORE", LONG2FIX(SSL_SESS_CACHE_NO_INTERNAL_STORE));
|
||||
rb_define_const(cSSLContext, "SESSION_CACHE_NO_INTERNAL", LONG2FIX(SSL_SESS_CACHE_NO_INTERNAL));
|
||||
rb_define_method(cSSLContext, "session_add", ossl_sslctx_session_add, 1);
|
||||
rb_define_method(cSSLContext, "session_remove", ossl_sslctx_session_remove, 1);
|
||||
rb_define_method(cSSLContext, "session_cache_mode", ossl_sslctx_get_session_cache_mode, 0);
|
||||
rb_define_method(cSSLContext, "session_cache_mode=", ossl_sslctx_set_session_cache_mode, 1);
|
||||
rb_define_method(cSSLContext, "session_cache_size", ossl_sslctx_get_session_cache_size, 0);
|
||||
rb_define_method(cSSLContext, "session_cache_size=", ossl_sslctx_set_session_cache_size, 1);
|
||||
rb_define_method(cSSLContext, "session_cache_stats", ossl_sslctx_get_session_cache_stats, 0);
|
||||
rb_define_method(cSSLContext, "flush_sessions", ossl_sslctx_flush_sessions, -1);
|
||||
|
||||
ary = rb_ary_new2(numberof(ossl_ssl_method_tab));
|
||||
for (i = 0; i < numberof(ossl_ssl_method_tab); i++) {
|
||||
rb_ary_push(ary, ID2SYM(rb_intern(ossl_ssl_method_tab[i].name)));
|
||||
}
|
||||
rb_obj_freeze(ary);
|
||||
/* holds a list of available SSL/TLS methods */
|
||||
rb_define_const(cSSLContext, "METHODS", ary);
|
||||
|
||||
/* class SSLSocket
|
||||
*
|
||||
* The following attributes are available but don't show up in rdoc.
|
||||
* * io, context, sync_close
|
||||
*
|
||||
*/
|
||||
cSSLSocket = rb_define_class_under(mSSL, "SSLSocket", rb_cObject);
|
||||
rb_define_alloc_func(cSSLSocket, ossl_ssl_s_alloc);
|
||||
for(i = 0; i < numberof(ossl_ssl_attr_readers); i++)
|
||||
|
@ -899,6 +1390,8 @@ Init_ossl_ssl()
|
|||
rb_define_method(cSSLSocket, "cipher", ossl_ssl_get_cipher, 0);
|
||||
rb_define_method(cSSLSocket, "state", ossl_ssl_get_state, 0);
|
||||
rb_define_method(cSSLSocket, "pending", ossl_ssl_pending, 0);
|
||||
rb_define_method(cSSLSocket, "session_reused?", ossl_ssl_session_reused, 0);
|
||||
rb_define_method(cSSLSocket, "session=", ossl_ssl_set_session, 1);
|
||||
|
||||
#define ossl_ssl_def_const(x) rb_define_const(mSSL, #x, INT2FIX(SSL_##x))
|
||||
|
||||
|
|
|
@ -11,11 +11,26 @@
|
|||
#if !defined(_OSSL_SSL_H_)
|
||||
#define _OSSL_SSL_H_
|
||||
|
||||
#define GetSSLSession(obj, sess) do { \
|
||||
Data_Get_Struct(obj, SSL_SESSION, sess); \
|
||||
if (!sess) { \
|
||||
ossl_raise(rb_eRuntimeError, "SSL Session wasn't initialized."); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define SafeGetSSLSession(obj, sess) do { \
|
||||
OSSL_Check_Kind(obj, cSSLSession); \
|
||||
GetSSLSession(obj, sess); \
|
||||
} while (0)
|
||||
|
||||
extern VALUE mSSL;
|
||||
extern VALUE eSSLError;
|
||||
extern VALUE cSSLSocket;
|
||||
extern VALUE cSSLContext;
|
||||
extern VALUE cSSLSession;
|
||||
|
||||
void Init_ossl_ssl(void);
|
||||
void Init_ossl_ssl_session(void);
|
||||
|
||||
#endif /* _OSSL_SSL_H_ */
|
||||
|
||||
|
|
292
ext/openssl/ossl_ssl_session.c
Normal file
292
ext/openssl/ossl_ssl_session.c
Normal file
|
@ -0,0 +1,292 @@
|
|||
/*
|
||||
* Copyright (C) 2004-2007 Technorama Ltd. <oss-ruby@technorama.net>
|
||||
*/
|
||||
|
||||
#include "ossl.h"
|
||||
|
||||
#define GetSSLSession(obj, sess) do { \
|
||||
Data_Get_Struct(obj, SSL_SESSION, sess); \
|
||||
if (!sess) { \
|
||||
ossl_raise(rb_eRuntimeError, "SSL Session wasn't initialized."); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define SafeGetSSLSession(obj, sess) do { \
|
||||
OSSL_Check_Kind(obj, cSSLSession); \
|
||||
GetSSLSession(obj, sess); \
|
||||
} while (0)
|
||||
|
||||
|
||||
VALUE cSSLSession;
|
||||
static VALUE eSSLSession;
|
||||
|
||||
static VALUE ossl_ssl_session_alloc(VALUE klass)
|
||||
{
|
||||
return Data_Wrap_Struct(klass, 0, SSL_SESSION_free, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* Session.new(SSLSocket | string) => session
|
||||
*
|
||||
* === Parameters
|
||||
* +SSLSocket+ is an OpenSSL::SSL::SSLSocket
|
||||
* +string+ must be a DER or PEM encoded Session.
|
||||
*/
|
||||
static VALUE ossl_ssl_session_initialize(VALUE self, VALUE arg1)
|
||||
{
|
||||
SSL_SESSION *ctx = NULL;
|
||||
VALUE obj;
|
||||
unsigned char *p;
|
||||
|
||||
if (RDATA(self)->data)
|
||||
ossl_raise(eSSLSession, "SSL Session already initialized");
|
||||
|
||||
if (rb_obj_is_instance_of(arg1, cSSLSocket)) {
|
||||
SSL *ssl;
|
||||
|
||||
Data_Get_Struct(arg1, SSL, ssl);
|
||||
|
||||
if ((ctx = SSL_get1_session(ssl)) == NULL)
|
||||
ossl_raise(eSSLSession, "no session available");
|
||||
} else {
|
||||
BIO *in = ossl_obj2bio(arg1);
|
||||
|
||||
ctx = PEM_read_bio_SSL_SESSION(in, NULL, NULL, NULL);
|
||||
|
||||
if (!ctx) {
|
||||
BIO_reset(in);
|
||||
ctx = d2i_SSL_SESSION_bio(in, NULL);
|
||||
}
|
||||
|
||||
BIO_free(in);
|
||||
|
||||
if (!ctx)
|
||||
ossl_raise(rb_eArgError, "unknown type");
|
||||
}
|
||||
|
||||
/* should not happen */
|
||||
if (ctx == NULL)
|
||||
ossl_raise(eSSLSession, "ctx not set - internal error");
|
||||
|
||||
RDATA(self)->data = ctx;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* session1 == session2 -> boolean
|
||||
*
|
||||
*/
|
||||
static VALUE ossl_ssl_session_eq(VALUE val1, VALUE val2)
|
||||
{
|
||||
SSL_SESSION *ctx1, *ctx2;
|
||||
|
||||
GetSSLSession(val1, ctx1);
|
||||
SafeGetSSLSession(val2, ctx2);
|
||||
|
||||
switch (SSL_SESSION_cmp(ctx1, ctx2)) {
|
||||
case 0: return Qtrue;
|
||||
default: return Qfalse;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* session.time -> Time
|
||||
*
|
||||
*/
|
||||
static VALUE ossl_ssl_session_get_time(VALUE self)
|
||||
{
|
||||
SSL_SESSION *ctx;
|
||||
time_t t;
|
||||
|
||||
GetSSLSession(self, ctx);
|
||||
|
||||
t = SSL_SESSION_get_time(ctx);
|
||||
|
||||
if (t == 0)
|
||||
return Qnil;
|
||||
|
||||
return rb_funcall(rb_cTime, rb_intern("at"), 1, LONG2NUM(t));
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* session.timeout -> integer
|
||||
*
|
||||
* How long until the session expires in seconds.
|
||||
*
|
||||
*/
|
||||
static VALUE ossl_ssl_session_get_timeout(VALUE self)
|
||||
{
|
||||
SSL_SESSION *ctx;
|
||||
time_t t;
|
||||
|
||||
GetSSLSession(self, ctx);
|
||||
|
||||
t = SSL_SESSION_get_timeout(ctx);
|
||||
|
||||
return ULONG2NUM(t);
|
||||
}
|
||||
|
||||
#define SSLSESSION_SET_TIME(func) \
|
||||
static VALUE ossl_ssl_session_set_##func(VALUE self, VALUE time_v) \
|
||||
{ \
|
||||
SSL_SESSION *ctx; \
|
||||
time_t t; \
|
||||
\
|
||||
GetSSLSession(self, ctx); \
|
||||
\
|
||||
if (rb_obj_is_instance_of(time_v, rb_cTime)) { \
|
||||
time_v = rb_funcall(time_v, rb_intern("to_i"), 0); \
|
||||
} else if (FIXNUM_P(time_v)) { \
|
||||
; \
|
||||
} else { \
|
||||
rb_raise(rb_eArgError, "unknown type"); \
|
||||
} \
|
||||
\
|
||||
t = NUM2ULONG(time_v); \
|
||||
\
|
||||
SSL_SESSION_set_##func(ctx, t); \
|
||||
\
|
||||
return ossl_ssl_session_get_##func(self); \
|
||||
}
|
||||
|
||||
SSLSESSION_SET_TIME(time)
|
||||
SSLSESSION_SET_TIME(timeout)
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* session.id -> aString
|
||||
*
|
||||
* Returns the Session ID.
|
||||
*/
|
||||
static VALUE ossl_ssl_session_get_id(VALUE self)
|
||||
{
|
||||
SSL_SESSION *ctx;
|
||||
const unsigned char *p = NULL;
|
||||
unsigned int i = 0;
|
||||
|
||||
GetSSLSession(self, ctx);
|
||||
|
||||
p = SSL_SESSION_get_id(ctx, &i);
|
||||
|
||||
return rb_str_new(p, i);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* session.to_der -> aString
|
||||
*
|
||||
* Returns an ASN1 encoded String that contains the Session object.
|
||||
*/
|
||||
static VALUE ossl_ssl_session_to_der(VALUE self)
|
||||
{
|
||||
SSL_SESSION *ctx;
|
||||
unsigned char buf[1024*10], *p;
|
||||
int len;
|
||||
|
||||
GetSSLSession(self, ctx);
|
||||
|
||||
p = buf;
|
||||
len = i2d_SSL_SESSION(ctx, &p);
|
||||
|
||||
if (len <= 0)
|
||||
ossl_raise(eSSLSession, "i2d_SSL_SESSION");
|
||||
else if (len >= sizeof(buf))
|
||||
ossl_raise(eSSLSession, "i2d_SSL_SESSION too large");
|
||||
|
||||
return rb_str_new(p, len);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* 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;
|
||||
BIO *out;
|
||||
BUF_MEM *buf;
|
||||
VALUE str;
|
||||
int i;
|
||||
|
||||
GetSSLSession(self, ctx);
|
||||
|
||||
if (!(out = BIO_new(BIO_s_mem()))) {
|
||||
ossl_raise(eSSLSession, "BIO_s_mem()");
|
||||
}
|
||||
|
||||
if (!(i=PEM_write_bio_SSL_SESSION(out, ctx))) {
|
||||
BIO_free(out);
|
||||
ossl_raise(eSSLSession, "SSL_SESSION_print()");
|
||||
}
|
||||
|
||||
BIO_get_mem_ptr(out, &buf);
|
||||
str = rb_str_new(buf->data, buf->length);
|
||||
BIO_free(out);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* session.to_text -> String
|
||||
*
|
||||
* Shows everything in the Session object.
|
||||
*/
|
||||
static VALUE ossl_ssl_session_to_text(VALUE self)
|
||||
{
|
||||
SSL_SESSION *ctx;
|
||||
BIO *out;
|
||||
BUF_MEM *buf;
|
||||
VALUE str;
|
||||
|
||||
GetSSLSession(self, ctx);
|
||||
|
||||
if (!(out = BIO_new(BIO_s_mem()))) {
|
||||
ossl_raise(eSSLSession, "BIO_s_mem()");
|
||||
}
|
||||
|
||||
if (!SSL_SESSION_print(out, ctx)) {
|
||||
BIO_free(out);
|
||||
ossl_raise(eSSLSession, "SSL_SESSION_print()");
|
||||
}
|
||||
|
||||
BIO_get_mem_ptr(out, &buf);
|
||||
str = rb_str_new(buf->data, buf->length);
|
||||
BIO_free(out);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
void Init_ossl_ssl_session(void)
|
||||
{
|
||||
#if 0 /* let rdoc know about mOSSL */
|
||||
mOSSL = rb_define_module("OpenSSL");
|
||||
mSSL = rb_define_module_under(mOSSL, "SSL");
|
||||
#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_method(cSSLSession, "==", ossl_ssl_session_eq, 1);
|
||||
|
||||
rb_define_method(cSSLSession, "time", ossl_ssl_session_get_time, 0);
|
||||
rb_define_method(cSSLSession, "time=", ossl_ssl_session_set_time, 1);
|
||||
rb_define_method(cSSLSession, "timeout", ossl_ssl_session_get_timeout, 0);
|
||||
rb_define_method(cSSLSession, "timeout=", ossl_ssl_session_set_timeout, 1);
|
||||
|
||||
rb_define_method(cSSLSession, "id", ossl_ssl_session_get_id, 0);
|
||||
rb_define_method(cSSLSession, "to_der", ossl_ssl_session_to_der, 0);
|
||||
rb_define_method(cSSLSession, "to_pem", ossl_ssl_session_to_pem, 0);
|
||||
rb_define_method(cSSLSession, "to_text", ossl_ssl_session_to_text, 0);
|
||||
}
|
|
@ -84,6 +84,10 @@ ossl_x509attr_alloc(VALUE klass)
|
|||
return obj;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* Attribute.new(oid [, value]) => attr
|
||||
*/
|
||||
static VALUE
|
||||
ossl_x509attr_initialize(int argc, VALUE *argv, VALUE self)
|
||||
{
|
||||
|
@ -95,9 +99,9 @@ ossl_x509attr_initialize(int argc, VALUE *argv, VALUE self)
|
|||
if(rb_scan_args(argc, argv, "11", &oid, &value) == 1){
|
||||
oid = ossl_to_der_if_possible(oid);
|
||||
StringValue(oid);
|
||||
p = RSTRING(oid)->ptr;
|
||||
p = RSTRING_PTR(oid);
|
||||
if(!d2i_X509_ATTRIBUTE((X509_ATTRIBUTE**)&DATA_PTR(self),
|
||||
&p, RSTRING(oid)->len)){
|
||||
&p, RSTRING_LEN(oid))){
|
||||
ossl_raise(eX509AttrError, NULL);
|
||||
}
|
||||
return self;
|
||||
|
@ -108,6 +112,10 @@ ossl_x509attr_initialize(int argc, VALUE *argv, VALUE self)
|
|||
return self;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* attr.oid = string => string
|
||||
*/
|
||||
static VALUE
|
||||
ossl_x509attr_set_oid(VALUE self, VALUE oid)
|
||||
{
|
||||
|
@ -125,6 +133,10 @@ ossl_x509attr_set_oid(VALUE self, VALUE oid)
|
|||
return oid;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* attr.oid => string
|
||||
*/
|
||||
static VALUE
|
||||
ossl_x509attr_get_oid(VALUE self)
|
||||
{
|
||||
|
@ -156,6 +168,10 @@ ossl_x509attr_get_oid(VALUE self)
|
|||
# define OSSL_X509ATTR_SET_SINGLE(attr) ((attr)->set = 0)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* attr.value = asn1 => asn1
|
||||
*/
|
||||
static VALUE
|
||||
ossl_x509attr_set_value(VALUE self, VALUE value)
|
||||
{
|
||||
|
@ -179,6 +195,10 @@ ossl_x509attr_set_value(VALUE self, VALUE value)
|
|||
return value;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* attr.value => asn1
|
||||
*/
|
||||
static VALUE
|
||||
ossl_x509attr_get_value(VALUE self)
|
||||
{
|
||||
|
@ -192,7 +212,7 @@ ossl_x509attr_get_value(VALUE self)
|
|||
if(OSSL_X509ATTR_IS_SINGLE(attr)){
|
||||
length = i2d_ASN1_TYPE(attr->value.single, NULL);
|
||||
str = rb_str_new(0, length);
|
||||
p = RSTRING(str)->ptr;
|
||||
p = RSTRING_PTR(str);
|
||||
i2d_ASN1_TYPE(attr->value.single, &p);
|
||||
ossl_str_adjust(str, p);
|
||||
}
|
||||
|
@ -200,7 +220,7 @@ ossl_x509attr_get_value(VALUE self)
|
|||
length = i2d_ASN1_SET_OF_ASN1_TYPE(attr->value.set, NULL,
|
||||
i2d_ASN1_TYPE, V_ASN1_SET, V_ASN1_UNIVERSAL, 0);
|
||||
str = rb_str_new(0, length);
|
||||
p = RSTRING(str)->ptr;
|
||||
p = RSTRING_PTR(str);
|
||||
i2d_ASN1_SET_OF_ASN1_TYPE(attr->value.set, &p,
|
||||
i2d_ASN1_TYPE, V_ASN1_SET, V_ASN1_UNIVERSAL, 0);
|
||||
ossl_str_adjust(str, p);
|
||||
|
@ -210,6 +230,10 @@ ossl_x509attr_get_value(VALUE self)
|
|||
return asn1;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* attr.to_der => string
|
||||
*/
|
||||
static VALUE
|
||||
ossl_x509attr_to_der(VALUE self)
|
||||
{
|
||||
|
@ -222,10 +246,10 @@ ossl_x509attr_to_der(VALUE self)
|
|||
if((len = i2d_X509_ATTRIBUTE(attr, NULL)) <= 0)
|
||||
ossl_raise(eX509AttrError, NULL);
|
||||
str = rb_str_new(0, len);
|
||||
p = RSTRING(str)->ptr;
|
||||
p = RSTRING_PTR(str);
|
||||
if(i2d_X509_ATTRIBUTE(attr, &p) <= 0)
|
||||
ossl_raise(eX509AttrError, NULL);
|
||||
RSTRING(str)->len = p - (unsigned char*)RSTRING(str)->ptr;
|
||||
rb_str_set_len(str, p - (unsigned char*)RSTRING_PTR(str));
|
||||
|
||||
return str;
|
||||
}
|
||||
|
|
|
@ -63,7 +63,7 @@ ossl_x509_new_from_file(VALUE filename)
|
|||
VALUE obj;
|
||||
|
||||
SafeStringValue(filename);
|
||||
if (!(fp = fopen(RSTRING(filename)->ptr, "r"))) {
|
||||
if (!(fp = fopen(RSTRING_PTR(filename), "r"))) {
|
||||
ossl_raise(eX509CertError, "%s", strerror(errno));
|
||||
}
|
||||
x509 = PEM_read_X509(fp, NULL, NULL, NULL);
|
||||
|
@ -125,6 +125,11 @@ ossl_x509_alloc(VALUE klass)
|
|||
return obj;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* Certificate.new => cert
|
||||
* Certificate.new(string) => cert
|
||||
*/
|
||||
static VALUE
|
||||
ossl_x509_initialize(int argc, VALUE *argv, VALUE self)
|
||||
{
|
||||
|
@ -169,6 +174,10 @@ ossl_x509_copy(VALUE self, VALUE other)
|
|||
return self;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* cert.to_der => string
|
||||
*/
|
||||
static VALUE
|
||||
ossl_x509_to_der(VALUE self)
|
||||
{
|
||||
|
@ -181,7 +190,7 @@ ossl_x509_to_der(VALUE self)
|
|||
if ((len = i2d_X509(x509, NULL)) <= 0)
|
||||
ossl_raise(eX509CertError, NULL);
|
||||
str = rb_str_new(0, len);
|
||||
p = RSTRING(str)->ptr;
|
||||
p = RSTRING_PTR(str);
|
||||
if (i2d_X509(x509, &p) <= 0)
|
||||
ossl_raise(eX509CertError, NULL);
|
||||
ossl_str_adjust(str, p);
|
||||
|
@ -189,6 +198,10 @@ ossl_x509_to_der(VALUE self)
|
|||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* cert.to_pem => string
|
||||
*/
|
||||
static VALUE
|
||||
ossl_x509_to_pem(VALUE self)
|
||||
{
|
||||
|
@ -209,6 +222,10 @@ ossl_x509_to_pem(VALUE self)
|
|||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* cert.to_text => string
|
||||
*/
|
||||
static VALUE
|
||||
ossl_x509_to_text(VALUE self)
|
||||
{
|
||||
|
@ -252,6 +269,10 @@ ossl_x509_to_req(VALUE self)
|
|||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* cert.version => integer
|
||||
*/
|
||||
static VALUE
|
||||
ossl_x509_get_version(VALUE self)
|
||||
{
|
||||
|
@ -262,6 +283,10 @@ ossl_x509_get_version(VALUE self)
|
|||
return LONG2NUM(X509_get_version(x509));
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* cert.version = integer => integer
|
||||
*/
|
||||
static VALUE
|
||||
ossl_x509_set_version(VALUE self, VALUE version)
|
||||
{
|
||||
|
@ -279,6 +304,10 @@ ossl_x509_set_version(VALUE self, VALUE version)
|
|||
return version;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* cert.serial => integer
|
||||
*/
|
||||
static VALUE
|
||||
ossl_x509_get_serial(VALUE self)
|
||||
{
|
||||
|
@ -289,6 +318,10 @@ ossl_x509_get_serial(VALUE self)
|
|||
return asn1integer_to_num(X509_get_serialNumber(x509));
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* cert.serial = integer => integer
|
||||
*/
|
||||
static VALUE
|
||||
ossl_x509_set_serial(VALUE self, VALUE num)
|
||||
{
|
||||
|
@ -302,6 +335,10 @@ ossl_x509_set_serial(VALUE self, VALUE num)
|
|||
return num;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* cert.signature_algorithm => string
|
||||
*/
|
||||
static VALUE
|
||||
ossl_x509_get_signature_algorithm(VALUE self)
|
||||
{
|
||||
|
@ -322,6 +359,10 @@ ossl_x509_get_signature_algorithm(VALUE self)
|
|||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* cert.subject => name
|
||||
*/
|
||||
static VALUE
|
||||
ossl_x509_get_subject(VALUE self)
|
||||
{
|
||||
|
@ -336,6 +377,10 @@ ossl_x509_get_subject(VALUE self)
|
|||
return ossl_x509name_new(name);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* cert.subject = name => name
|
||||
*/
|
||||
static VALUE
|
||||
ossl_x509_set_subject(VALUE self, VALUE subject)
|
||||
{
|
||||
|
@ -349,6 +394,10 @@ ossl_x509_set_subject(VALUE self, VALUE subject)
|
|||
return subject;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* cert.issuer => name
|
||||
*/
|
||||
static VALUE
|
||||
ossl_x509_get_issuer(VALUE self)
|
||||
{
|
||||
|
@ -363,6 +412,10 @@ ossl_x509_get_issuer(VALUE self)
|
|||
return ossl_x509name_new(name);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* cert.issuer = name => name
|
||||
*/
|
||||
static VALUE
|
||||
ossl_x509_set_issuer(VALUE self, VALUE issuer)
|
||||
{
|
||||
|
@ -376,6 +429,10 @@ ossl_x509_set_issuer(VALUE self, VALUE issuer)
|
|||
return issuer;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* cert.not_before => time
|
||||
*/
|
||||
static VALUE
|
||||
ossl_x509_get_not_before(VALUE self)
|
||||
{
|
||||
|
@ -390,6 +447,10 @@ ossl_x509_get_not_before(VALUE self)
|
|||
return asn1time_to_time(asn1time);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* cert.not_before = time => time
|
||||
*/
|
||||
static VALUE
|
||||
ossl_x509_set_not_before(VALUE self, VALUE time)
|
||||
{
|
||||
|
@ -405,6 +466,10 @@ ossl_x509_set_not_before(VALUE self, VALUE time)
|
|||
return time;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* cert.not_after => time
|
||||
*/
|
||||
static VALUE
|
||||
ossl_x509_get_not_after(VALUE self)
|
||||
{
|
||||
|
@ -419,6 +484,10 @@ ossl_x509_get_not_after(VALUE self)
|
|||
return asn1time_to_time(asn1time);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* cert.not_before = time => time
|
||||
*/
|
||||
static VALUE
|
||||
ossl_x509_set_not_after(VALUE self, VALUE time)
|
||||
{
|
||||
|
@ -434,6 +503,10 @@ ossl_x509_set_not_after(VALUE self, VALUE time)
|
|||
return time;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* cert.public_key => key
|
||||
*/
|
||||
static VALUE
|
||||
ossl_x509_get_public_key(VALUE self)
|
||||
{
|
||||
|
@ -448,6 +521,10 @@ ossl_x509_get_public_key(VALUE self)
|
|||
return ossl_pkey_new(pkey); /* NO DUP - OK */
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* cert.public_key = key => key
|
||||
*/
|
||||
static VALUE
|
||||
ossl_x509_set_public_key(VALUE self, VALUE key)
|
||||
{
|
||||
|
@ -461,6 +538,10 @@ ossl_x509_set_public_key(VALUE self, VALUE key)
|
|||
return key;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* cert.sign(key, digest) => self
|
||||
*/
|
||||
static VALUE
|
||||
ossl_x509_sign(VALUE self, VALUE key, VALUE digest)
|
||||
{
|
||||
|
@ -479,6 +560,9 @@ ossl_x509_sign(VALUE self, VALUE key, VALUE digest)
|
|||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* cert.verify(key) => true | false
|
||||
*
|
||||
* Checks that cert signature is made with PRIVversion of this PUBLIC 'key'
|
||||
*/
|
||||
static VALUE
|
||||
|
@ -501,6 +585,9 @@ ossl_x509_verify(VALUE self, VALUE key)
|
|||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* cert.check_private_key(key)
|
||||
*
|
||||
* Checks if 'key' is PRIV key for this cert
|
||||
*/
|
||||
static VALUE
|
||||
|
@ -521,7 +608,8 @@ ossl_x509_check_private_key(VALUE self, VALUE key)
|
|||
}
|
||||
|
||||
/*
|
||||
* Gets X509v3 extensions as array of X509Ext objects
|
||||
* call-seq:
|
||||
* cert.extensions => [extension...]
|
||||
*/
|
||||
static VALUE
|
||||
ossl_x509_get_extensions(VALUE self)
|
||||
|
@ -546,7 +634,8 @@ ossl_x509_get_extensions(VALUE self)
|
|||
}
|
||||
|
||||
/*
|
||||
* Sets X509_EXTENSIONs
|
||||
* call-seq:
|
||||
* cert.extensions = [ext...] => [ext...]
|
||||
*/
|
||||
static VALUE
|
||||
ossl_x509_set_extensions(VALUE self, VALUE ary)
|
||||
|
@ -557,14 +646,14 @@ ossl_x509_set_extensions(VALUE self, VALUE ary)
|
|||
|
||||
Check_Type(ary, T_ARRAY);
|
||||
/* All ary's members should be X509Extension */
|
||||
for (i=0; i<RARRAY(ary)->len; i++) {
|
||||
OSSL_Check_Kind(RARRAY(ary)->ptr[i], cX509Ext);
|
||||
for (i=0; i<RARRAY_LEN(ary); i++) {
|
||||
OSSL_Check_Kind(RARRAY_PTR(ary)[i], cX509Ext);
|
||||
}
|
||||
GetX509(self, x509);
|
||||
sk_X509_EXTENSION_pop_free(x509->cert_info->extensions, X509_EXTENSION_free);
|
||||
x509->cert_info->extensions = NULL;
|
||||
for (i=0; i<RARRAY(ary)->len; i++) {
|
||||
ext = DupX509ExtPtr(RARRAY(ary)->ptr[i]);
|
||||
for (i=0; i<RARRAY_LEN(ary); i++) {
|
||||
ext = DupX509ExtPtr(RARRAY_PTR(ary)[i]);
|
||||
|
||||
if (!X509_add_ext(x509, ext, -1)) { /* DUPs ext - FREE it */
|
||||
X509_EXTENSION_free(ext);
|
||||
|
@ -576,6 +665,10 @@ ossl_x509_set_extensions(VALUE self, VALUE ary)
|
|||
return ary;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* cert.add_extension(extension) => extension
|
||||
*/
|
||||
static VALUE
|
||||
ossl_x509_add_extension(VALUE self, VALUE extension)
|
||||
{
|
||||
|
|
|
@ -287,14 +287,14 @@ ossl_x509crl_set_revoked(VALUE self, VALUE ary)
|
|||
|
||||
Check_Type(ary, T_ARRAY);
|
||||
/* All ary members should be X509 Revoked */
|
||||
for (i=0; i<RARRAY(ary)->len; i++) {
|
||||
OSSL_Check_Kind(RARRAY(ary)->ptr[i], cX509Rev);
|
||||
for (i=0; i<RARRAY_LEN(ary); i++) {
|
||||
OSSL_Check_Kind(RARRAY_PTR(ary)[i], cX509Rev);
|
||||
}
|
||||
GetX509CRL(self, crl);
|
||||
sk_X509_REVOKED_pop_free(crl->crl->revoked, X509_REVOKED_free);
|
||||
crl->crl->revoked = NULL;
|
||||
for (i=0; i<RARRAY(ary)->len; i++) {
|
||||
rev = DupX509RevokedPtr(RARRAY(ary)->ptr[i]);
|
||||
for (i=0; i<RARRAY_LEN(ary); i++) {
|
||||
rev = DupX509RevokedPtr(RARRAY_PTR(ary)[i]);
|
||||
if (!X509_CRL_add0_revoked(crl, rev)) { /* NO DUP - don't free! */
|
||||
ossl_raise(eX509CRLError, NULL);
|
||||
}
|
||||
|
@ -461,14 +461,14 @@ ossl_x509crl_set_extensions(VALUE self, VALUE ary)
|
|||
|
||||
Check_Type(ary, T_ARRAY);
|
||||
/* All ary members should be X509 Extensions */
|
||||
for (i=0; i<RARRAY(ary)->len; i++) {
|
||||
OSSL_Check_Kind(RARRAY(ary)->ptr[i], cX509Ext);
|
||||
for (i=0; i<RARRAY_LEN(ary); i++) {
|
||||
OSSL_Check_Kind(RARRAY_PTR(ary)[i], cX509Ext);
|
||||
}
|
||||
GetX509CRL(self, crl);
|
||||
sk_X509_EXTENSION_pop_free(crl->crl->extensions, X509_EXTENSION_free);
|
||||
crl->crl->extensions = NULL;
|
||||
for (i=0; i<RARRAY(ary)->len; i++) {
|
||||
ext = DupX509ExtPtr(RARRAY(ary)->ptr[i]);
|
||||
for (i=0; i<RARRAY_LEN(ary); i++) {
|
||||
ext = DupX509ExtPtr(RARRAY_PTR(ary)[i]);
|
||||
if(!X509_CRL_add_ext(crl, ext, -1)) { /* DUPs ext - FREE it */
|
||||
X509_EXTENSION_free(ext);
|
||||
ossl_raise(eX509CRLError, NULL);
|
||||
|
|
|
@ -229,23 +229,23 @@ ossl_x509extfactory_create_ext(int argc, VALUE *argv, VALUE self)
|
|||
StringValue(value);
|
||||
if(NIL_P(critical)) critical = Qfalse;
|
||||
|
||||
nid = OBJ_ln2nid(RSTRING(oid)->ptr);
|
||||
if(!nid) nid = OBJ_sn2nid(RSTRING(oid)->ptr);
|
||||
if(!nid) ossl_raise(eX509ExtError, "unknown OID `%s'", RSTRING(oid)->ptr);
|
||||
nid = OBJ_ln2nid(RSTRING_PTR(oid));
|
||||
if(!nid) nid = OBJ_sn2nid(RSTRING_PTR(oid));
|
||||
if(!nid) ossl_raise(eX509ExtError, "unknown OID `%s'", RSTRING_PTR(oid));
|
||||
valstr = rb_str_new2(RTEST(critical) ? "critical," : "");
|
||||
rb_str_append(valstr, value);
|
||||
GetX509ExtFactory(self, ctx);
|
||||
#ifdef HAVE_X509V3_EXT_NCONF_NID
|
||||
rconf = rb_iv_get(self, "@config");
|
||||
conf = NIL_P(rconf) ? NULL : GetConfigPtr(rconf);
|
||||
ext = X509V3_EXT_nconf_nid(conf, ctx, nid, RSTRING(valstr)->ptr);
|
||||
ext = X509V3_EXT_nconf_nid(conf, ctx, nid, RSTRING_PTR(valstr));
|
||||
#else
|
||||
if (!empty_lhash) empty_lhash = lh_new(NULL, NULL);
|
||||
ext = X509V3_EXT_conf_nid(empty_lhash, ctx, nid, RSTRING(valstr)->ptr);
|
||||
ext = X509V3_EXT_conf_nid(empty_lhash, ctx, nid, RSTRING_PTR(valstr));
|
||||
#endif
|
||||
if (!ext){
|
||||
ossl_raise(eX509ExtError, "%s = %s",
|
||||
RSTRING(oid)->ptr, RSTRING(value)->ptr);
|
||||
RSTRING_PTR(oid), RSTRING_PTR(value));
|
||||
}
|
||||
WrapX509Ext(cX509Ext, obj, ext);
|
||||
|
||||
|
@ -280,9 +280,9 @@ ossl_x509ext_initialize(int argc, VALUE *argv, VALUE self)
|
|||
if(rb_scan_args(argc, argv, "12", &oid, &value, &critical) == 1){
|
||||
oid = ossl_to_der_if_possible(oid);
|
||||
StringValue(oid);
|
||||
p = RSTRING(oid)->ptr;
|
||||
p = RSTRING_PTR(oid);
|
||||
if(!d2i_X509_EXTENSION((X509_EXTENSION**)&DATA_PTR(self),
|
||||
&p, RSTRING(oid)->len))
|
||||
&p, RSTRING_LEN(oid)))
|
||||
ossl_raise(eX509ExtError, NULL);
|
||||
return self;
|
||||
}
|
||||
|
@ -319,14 +319,14 @@ ossl_x509ext_set_value(VALUE self, VALUE data)
|
|||
|
||||
data = ossl_to_der_if_possible(data);
|
||||
StringValue(data);
|
||||
if(!(s = OPENSSL_malloc(RSTRING(data)->len)))
|
||||
if(!(s = OPENSSL_malloc(RSTRING_LEN(data))))
|
||||
ossl_raise(eX509ExtError, "malloc error");
|
||||
memcpy(s, RSTRING(data)->ptr, RSTRING(data)->len);
|
||||
memcpy(s, RSTRING_PTR(data), RSTRING_LEN(data));
|
||||
if(!(asn1s = ASN1_OCTET_STRING_new())){
|
||||
free(s);
|
||||
ossl_raise(eX509ExtError, NULL);
|
||||
}
|
||||
if(!M_ASN1_OCTET_STRING_set(asn1s, s, RSTRING(data)->len)){
|
||||
if(!M_ASN1_OCTET_STRING_set(asn1s, s, RSTRING_LEN(data))){
|
||||
free(s);
|
||||
ASN1_OCTET_STRING_free(asn1s);
|
||||
ossl_raise(eX509ExtError, NULL);
|
||||
|
@ -409,7 +409,7 @@ ossl_x509ext_to_der(VALUE obj)
|
|||
if((len = i2d_X509_EXTENSION(ext, NULL)) <= 0)
|
||||
ossl_raise(eX509ExtError, NULL);
|
||||
str = rb_str_new(0, len);
|
||||
p = RSTRING(str)->ptr;
|
||||
p = RSTRING_PTR(str);
|
||||
if(i2d_X509_EXTENSION(ext, &p) < 0)
|
||||
ossl_raise(eX509ExtError, NULL);
|
||||
ossl_str_adjust(str, p);
|
||||
|
|
|
@ -109,6 +109,13 @@ ossl_x509name_init_i(VALUE i, VALUE args)
|
|||
return Qnil;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* X509::Name.new => name
|
||||
* X509::Name.new(string) => name
|
||||
* X509::Name.new(dn) => name
|
||||
* X509::Name.new(dn, template) => name
|
||||
*/
|
||||
static VALUE
|
||||
ossl_x509name_initialize(int argc, VALUE *argv, VALUE self)
|
||||
{
|
||||
|
@ -125,14 +132,14 @@ ossl_x509name_initialize(int argc, VALUE *argv, VALUE self)
|
|||
VALUE args;
|
||||
if(NIL_P(template)) template = OBJECT_TYPE_TEMPLATE;
|
||||
args = rb_ary_new3(2, self, template);
|
||||
rb_iterate(rb_each, tmp, ossl_x509name_init_i, args);
|
||||
rb_block_call(tmp, rb_intern("each"), 0, 0, ossl_x509name_init_i, args);
|
||||
}
|
||||
else{
|
||||
unsigned char *p;
|
||||
VALUE str = ossl_to_der_if_possible(arg);
|
||||
StringValue(str);
|
||||
p = RSTRING(str)->ptr;
|
||||
if(!d2i_X509_NAME((X509_NAME**)&DATA_PTR(self), &p, RSTRING(str)->len)){
|
||||
p = RSTRING_PTR(str);
|
||||
if(!d2i_X509_NAME((X509_NAME**)&DATA_PTR(self), &p, RSTRING_LEN(str))){
|
||||
ossl_raise(eX509NameError, NULL);
|
||||
}
|
||||
}
|
||||
|
@ -141,6 +148,10 @@ ossl_x509name_initialize(int argc, VALUE *argv, VALUE self)
|
|||
return self;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* name.add_entry(oid, value [, type]) => self
|
||||
*/
|
||||
static
|
||||
VALUE ossl_x509name_add_entry(int argc, VALUE *argv, VALUE self)
|
||||
{
|
||||
|
@ -152,8 +163,8 @@ VALUE ossl_x509name_add_entry(int argc, VALUE *argv, VALUE self)
|
|||
StringValue(value);
|
||||
if(NIL_P(type)) type = rb_aref(OBJECT_TYPE_TEMPLATE, oid);
|
||||
GetX509Name(self, name);
|
||||
if (!X509_NAME_add_entry_by_txt(name, RSTRING(oid)->ptr, NUM2INT(type),
|
||||
RSTRING(value)->ptr, RSTRING(value)->len, -1, 0)) {
|
||||
if (!X509_NAME_add_entry_by_txt(name, RSTRING_PTR(oid), NUM2INT(type),
|
||||
RSTRING_PTR(value), RSTRING_LEN(value), -1, 0)) {
|
||||
ossl_raise(eX509NameError, NULL);
|
||||
}
|
||||
|
||||
|
@ -175,6 +186,11 @@ ossl_x509name_to_s_old(VALUE self)
|
|||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* name.to_s => string
|
||||
* name.to_s(integer) => string
|
||||
*/
|
||||
static VALUE
|
||||
ossl_x509name_to_s(int argc, VALUE *argv, VALUE self)
|
||||
{
|
||||
|
@ -199,6 +215,10 @@ ossl_x509name_to_s(int argc, VALUE *argv, VALUE self)
|
|||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* name.to_a => [[name, data, type], ...]
|
||||
*/
|
||||
static VALUE
|
||||
ossl_x509name_to_a(VALUE self)
|
||||
{
|
||||
|
@ -266,6 +286,10 @@ ossl_x509name_eql(VALUE self, VALUE other)
|
|||
return (result == 0) ? Qtrue : Qfalse;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* name.hash => integer
|
||||
*/
|
||||
static VALUE
|
||||
ossl_x509name_hash(VALUE self)
|
||||
{
|
||||
|
@ -279,6 +303,10 @@ ossl_x509name_hash(VALUE self)
|
|||
return ULONG2NUM(hash);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* name.to_der => string
|
||||
*/
|
||||
static VALUE
|
||||
ossl_x509name_to_der(VALUE self)
|
||||
{
|
||||
|
@ -291,7 +319,7 @@ ossl_x509name_to_der(VALUE self)
|
|||
if((len = i2d_X509_NAME(name, NULL)) <= 0)
|
||||
ossl_raise(eX509NameError, NULL);
|
||||
str = rb_str_new(0, len);
|
||||
p = RSTRING(str)->ptr;
|
||||
p = RSTRING_PTR(str);
|
||||
if(i2d_X509_NAME(name, &p) <= 0)
|
||||
ossl_raise(eX509NameError, NULL);
|
||||
ossl_str_adjust(str, p);
|
||||
|
|
|
@ -171,7 +171,7 @@ ossl_x509req_to_der(VALUE self)
|
|||
if ((len = i2d_X509_REQ(req, NULL)) <= 0)
|
||||
ossl_raise(eX509CertError, NULL);
|
||||
str = rb_str_new(0, len);
|
||||
p = RSTRING(str)->ptr;
|
||||
p = RSTRING_PTR(str);
|
||||
if (i2d_X509_REQ(req, &p) <= 0)
|
||||
ossl_raise(eX509ReqError, NULL);
|
||||
ossl_str_adjust(str, p);
|
||||
|
@ -403,14 +403,14 @@ ossl_x509req_set_attributes(VALUE self, VALUE ary)
|
|||
VALUE item;
|
||||
|
||||
Check_Type(ary, T_ARRAY);
|
||||
for (i=0;i<RARRAY(ary)->len; i++) {
|
||||
OSSL_Check_Kind(RARRAY(ary)->ptr[i], cX509Attr);
|
||||
for (i=0;i<RARRAY_LEN(ary); i++) {
|
||||
OSSL_Check_Kind(RARRAY_PTR(ary)[i], cX509Attr);
|
||||
}
|
||||
GetX509Req(self, req);
|
||||
sk_X509_ATTRIBUTE_pop_free(req->req_info->attributes, X509_ATTRIBUTE_free);
|
||||
req->req_info->attributes = NULL;
|
||||
for (i=0;i<RARRAY(ary)->len; i++) {
|
||||
item = RARRAY(ary)->ptr[i];
|
||||
for (i=0;i<RARRAY_LEN(ary); i++) {
|
||||
item = RARRAY_PTR(ary)[i];
|
||||
attr = DupX509AttrPtr(item);
|
||||
if (!X509_REQ_add1_attr(req, attr)) {
|
||||
ossl_raise(eX509ReqError, NULL);
|
||||
|
|
|
@ -175,14 +175,14 @@ ossl_x509revoked_set_extensions(VALUE self, VALUE ary)
|
|||
VALUE item;
|
||||
|
||||
Check_Type(ary, T_ARRAY);
|
||||
for (i=0; i<RARRAY(ary)->len; i++) {
|
||||
OSSL_Check_Kind(RARRAY(ary)->ptr[i], cX509Ext);
|
||||
for (i=0; i<RARRAY_LEN(ary); i++) {
|
||||
OSSL_Check_Kind(RARRAY_PTR(ary)[i], cX509Ext);
|
||||
}
|
||||
GetX509Rev(self, rev);
|
||||
sk_X509_EXTENSION_pop_free(rev->extensions, X509_EXTENSION_free);
|
||||
rev->extensions = NULL;
|
||||
for (i=0; i<RARRAY(ary)->len; i++) {
|
||||
item = RARRAY(ary)->ptr[i];
|
||||
for (i=0; i<RARRAY_LEN(ary); i++) {
|
||||
item = RARRAY_PTR(ary)[i];
|
||||
ext = DupX509ExtPtr(item);
|
||||
if(!X509_REVOKED_add_ext(rev, ext, -1)) {
|
||||
ossl_raise(eX509RevError, NULL);
|
||||
|
|
|
@ -118,11 +118,18 @@ ossl_x509store_set_vfy_cb(VALUE self, VALUE cb)
|
|||
return cb;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* X509::Store.new => store
|
||||
*
|
||||
*/
|
||||
static VALUE
|
||||
ossl_x509store_initialize(int argc, VALUE *argv, VALUE self)
|
||||
{
|
||||
X509_STORE *store;
|
||||
|
||||
/* BUG: This method takes any number of arguments but appears to ignore them. */
|
||||
GetX509Store(self, store);
|
||||
X509_STORE_set_verify_cb_func(store, ossl_verify_cb);
|
||||
ossl_x509store_set_vfy_cb(self, Qnil);
|
||||
|
@ -206,7 +213,7 @@ ossl_x509store_add_file(VALUE self, VALUE file)
|
|||
|
||||
if(file != Qnil){
|
||||
Check_SafeStr(file);
|
||||
path = RSTRING(file)->ptr;
|
||||
path = RSTRING_PTR(file);
|
||||
}
|
||||
GetX509Store(self, store);
|
||||
lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
|
||||
|
@ -227,7 +234,7 @@ ossl_x509store_add_path(VALUE self, VALUE dir)
|
|||
|
||||
if(dir != Qnil){
|
||||
Check_SafeStr(dir);
|
||||
path = RSTRING(dir)->ptr;
|
||||
path = RSTRING_PTR(dir);
|
||||
}
|
||||
GetX509Store(self, store);
|
||||
lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir());
|
||||
|
@ -550,6 +557,10 @@ ossl_x509stctx_set_trust(VALUE self, VALUE trust)
|
|||
return trust;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* storectx.time = time => time
|
||||
*/
|
||||
static VALUE
|
||||
ossl_x509stctx_set_time(VALUE self, VALUE time)
|
||||
{
|
||||
|
|
|
@ -9,10 +9,33 @@
|
|||
* (See the file 'LICENCE'.)
|
||||
*/
|
||||
#if !defined(_OSSL_RUBY_MISSING_H_)
|
||||
#define _OSS_RUBY_MISSING_H_
|
||||
#define _OSSL_RUBY_MISSING_H_
|
||||
|
||||
#define rb_define_copy_func(klass, func) \
|
||||
rb_define_method(klass, "initialize_copy", func, 1)
|
||||
|
||||
#endif /* _OSS_RUBY_MISSING_H_ */
|
||||
|
||||
#ifndef GetReadFile
|
||||
#define FPTR_TO_FD(fptr) (fptr->fd)
|
||||
#else
|
||||
#define FPTR_TO_FD(fptr) (fileno(GetReadFile(fptr)))
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_RB_IO_T
|
||||
#define rb_io_t OpenFile
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_RB_STR_SET_LEN
|
||||
/* these methods should probably be backported to 1.8 */
|
||||
#define rb_str_set_len(str, length) do { \
|
||||
RSTRING(str)->ptr[length] = 0; \
|
||||
RSTRING(str)->len = length; \
|
||||
} while(0)
|
||||
#endif /* ! HAVE_RB_STR_SET_LEN */
|
||||
|
||||
#ifndef HAVE_RB_BLOCK_CALL
|
||||
/* the openssl module doesn't use arg[3-4] and arg2 is always rb_each */
|
||||
#define rb_block_call(arg1, arg2, arg3, arg4, arg5, arg6) rb_iterate(rb_each, arg1, arg5, arg6)
|
||||
#endif /* ! HAVE_RB_BLOCK_CALL */
|
||||
|
||||
#endif /* _OSSL_RUBY_MISSING_H_ */
|
||||
|
|
113
test/openssl/test_ec.rb
Normal file
113
test/openssl/test_ec.rb
Normal file
|
@ -0,0 +1,113 @@
|
|||
begin
|
||||
require "openssl"
|
||||
require File.join(File.dirname(__FILE__), "utils.rb")
|
||||
rescue LoadError
|
||||
end
|
||||
require "test/unit"
|
||||
|
||||
if defined?(OpenSSL)
|
||||
|
||||
class OpenSSL::TestEC < Test::Unit::TestCase
|
||||
def setup
|
||||
@data1 = 'foo'
|
||||
@data2 = 'bar' * 1000 # data too long for DSA sig
|
||||
|
||||
@group1 = OpenSSL::PKey::EC::Group.new('secp112r1')
|
||||
@group2 = OpenSSL::PKey::EC::Group.new('sect163k1')
|
||||
|
||||
@key1 = OpenSSL::PKey::EC.new
|
||||
@key1.group = @group1
|
||||
@key1.generate_key
|
||||
|
||||
@key2 = OpenSSL::PKey::EC.new(@group2.curve_name)
|
||||
@key2.generate_key
|
||||
|
||||
@groups = [@group1, @group2]
|
||||
@keys = [@key1, @key2]
|
||||
end
|
||||
|
||||
def compare_keys(k1, k2)
|
||||
assert_equal(k1.to_pem, k2.to_pem)
|
||||
end
|
||||
|
||||
def test_curve_names
|
||||
@groups.each_with_index do |group, idx|
|
||||
key = @keys[idx]
|
||||
assert_equal(group.curve_name, key.group.curve_name)
|
||||
end
|
||||
end
|
||||
|
||||
def test_check_key
|
||||
for key in @keys
|
||||
assert_equal(key.check_key, true)
|
||||
assert_equal(key.private_key?, true)
|
||||
assert_equal(key.public_key?, true)
|
||||
end
|
||||
end
|
||||
|
||||
def test_encoding
|
||||
for group in @groups
|
||||
for meth in [:to_der, :to_pem]
|
||||
txt = group.send(meth)
|
||||
gr = OpenSSL::PKey::EC::Group.new(txt)
|
||||
assert_equal(txt, gr.send(meth))
|
||||
|
||||
assert_equal(group.generator.to_bn, gr.generator.to_bn)
|
||||
assert_equal(group.cofactor, gr.cofactor)
|
||||
assert_equal(group.order, gr.order)
|
||||
assert_equal(group.seed, gr.seed)
|
||||
assert_equal(group.degree, gr.degree)
|
||||
end
|
||||
end
|
||||
|
||||
for key in @keys
|
||||
group = key.group
|
||||
|
||||
for meth in [:to_der, :to_pem]
|
||||
txt = key.send(meth)
|
||||
assert_equal(txt, OpenSSL::PKey::EC.new(txt).send(meth))
|
||||
end
|
||||
|
||||
bn = key.public_key.to_bn
|
||||
assert_equal(bn, OpenSSL::PKey::EC::Point.new(group, bn).to_bn)
|
||||
end
|
||||
end
|
||||
|
||||
def test_set_keys
|
||||
for key in @keys
|
||||
k = OpenSSL::PKey::EC.new
|
||||
k.group = key.group
|
||||
k.private_key = key.private_key
|
||||
k.public_key = key.public_key
|
||||
|
||||
compare_keys(key, k)
|
||||
end
|
||||
end
|
||||
|
||||
def test_dsa_sign_verify
|
||||
for key in @keys
|
||||
sig = key.dsa_sign_asn1(@data1)
|
||||
assert_equal(key.dsa_verify_asn1(@data1, sig), true)
|
||||
|
||||
assert_raises(OpenSSL::PKey::ECError) { key.dsa_sign_asn1(@data2) }
|
||||
end
|
||||
end
|
||||
|
||||
def test_dh_compute_key
|
||||
for key in @keys
|
||||
k = OpenSSL::PKey::EC.new(key.group)
|
||||
k.generate_key
|
||||
|
||||
puba = key.public_key
|
||||
pubb = k.public_key
|
||||
a = key.dh_compute_key(pubb)
|
||||
b = k.dh_compute_key(puba)
|
||||
assert_equal(a, b)
|
||||
end
|
||||
end
|
||||
|
||||
# test Group: asn1_flag, point_conversion
|
||||
|
||||
end
|
||||
|
||||
end
|
Loading…
Add table
Add a link
Reference in a new issue