1
0
Fork 0
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:
technorama 2007-06-08 15:02:04 +00:00
parent f5be4ddc8d
commit 18342ff8e0
48 changed files with 3828 additions and 365 deletions

20
NEWS
View file

@ -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

View file

@ -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")

View file

@ -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'

View file

@ -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

View file

@ -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
def random_key
str = OpenSSL::Random.random_bytes(self.key_len)
self.key = str
return str
end
# 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
def random_iv
str = OpenSSL::Random.random_bytes(self.iv_len)
self.iv = 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

View file

@ -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

View 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

View file

@ -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

View file

@ -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();

View file

@ -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)
/*

View file

@ -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);
}

View file

@ -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);
}
if (!bio) ossl_raise(eOSSLError, NULL);
return bio;
}

View file

@ -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);
@ -489,10 +592,15 @@ ossl_bn_s_generate_prime(int argc, VALUE *argv, VALUE klass)
}
WrapBN(klass, obj, result);
return obj;
return obj;
}
#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. */
/*

View file

@ -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_ */

View file

@ -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);
}

View file

@ -11,7 +11,6 @@
#if !defined(_OSSL_CIPHER_H_)
#define _OSSL_CIPHER_H_
extern VALUE mCipher;
extern VALUE cCipher;
extern VALUE eCipherError;

View file

@ -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;
}

View file

@ -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)
{
EVP_MD_CTX *ctx;
const EVP_MD *md;
SafeGetDigest(obj, ctx);
if (TYPE(obj) == T_STRING) {
const char *name = STR2CSTR(obj);
return EVP_MD_CTX_md(ctx); /*== ctx->digest*/
md = EVP_get_digestbyname(name);
if (!md)
ossl_raise(rb_eRuntimeError, "Unsupported digest algorithm (%s).", name);
} else {
EVP_MD_CTX *ctx;
SafeGetDigest(obj, ctx);
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);

View file

@ -11,7 +11,6 @@
#if !defined(_OSSL_DIGEST_H_)
#define _OSSL_DIGEST_H_
extern VALUE mDigest;
extern VALUE cDigest;
extern VALUE eDigestError;

View file

@ -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;

View file

@ -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);

View file

@ -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);
}

View file

@ -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;

View file

@ -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);

View file

@ -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
View 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);
}

View file

@ -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);

View file

@ -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;

View file

@ -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();
}

View file

@ -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; \

View file

@ -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,7 +317,10 @@ ossl_dh_to_text(VALUE self)
}
/*
* Makes new instance DH PUBLIC_KEY from PRIVATE_KEY
* call-seq:
* dh.public_key -> aDH
*
* Makes new instance DH PUBLIC_KEY from PRIVATE_KEY
*/
static VALUE
ossl_dh_to_public_key(VALUE self)
@ -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;
}
@ -406,7 +477,7 @@ ossl_create_dh(unsigned char *p, size_t plen, unsigned char *g, size_t glen)
dh->g = BN_bin2bn(g, glen, NULL);
if (dh->p == NULL || dh->g == NULL){
DH_free(dh);
ossl_raise(eDHError, NULL);
ossl_raise(eDHError, NULL);
}
return dh;

View file

@ -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

File diff suppressed because it is too large Load diff

View file

@ -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)

View file

@ -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;

View file

@ -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)){
ossl_raise(eSSLError, "SSL_CTX_set_session_id_context:");
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))

View file

@ -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_ */

View 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);
}

View file

@ -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;
}

View file

@ -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)
{

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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)
{

View file

@ -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
View 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