Skip to content

Commit

Permalink
rewriting most of the asn1 init code in ruby
Browse files Browse the repository at this point in the history
to have as much of the lib in ruby as possible
  • Loading branch information
HoneyryderChuck committed Apr 16, 2024
1 parent a8caa63 commit a492c19
Show file tree
Hide file tree
Showing 3 changed files with 170 additions and 49 deletions.
99 changes: 50 additions & 49 deletions ext/openssl/ossl_asn1.c
Original file line number Diff line number Diff line change
Expand Up @@ -654,18 +654,18 @@ ossl_asn1_class2sym(int tc)
* asn1_int = OpenSSL::ASN1Data.new(42, 2, :UNIVERSAL) # => Same as OpenSSL::ASN1::Integer.new(42)
* tagged_int = OpenSSL::ASN1Data.new(42, 0, :CONTEXT_SPECIFIC) # implicitly 0-tagged INTEGER
*/
static VALUE
ossl_asn1data_initialize(VALUE self, VALUE value, VALUE tag, VALUE tag_class)
{
if(!SYMBOL_P(tag_class))
ossl_raise(eASN1Error, "invalid tag class");
ossl_asn1_set_tag(self, tag);
ossl_asn1_set_value(self, value);
ossl_asn1_set_tag_class(self, tag_class);
ossl_asn1_set_indefinite_length(self, Qfalse);

return self;
}
// static VALUE
// ossl_asn1data_initialize(VALUE self, VALUE value, VALUE tag, VALUE tag_class)
// {
// if(!SYMBOL_P(tag_class))
// ossl_raise(eASN1Error, "invalid tag class");
// ossl_asn1_set_tag(self, tag);
// ossl_asn1_set_value(self, value);
// ossl_asn1_set_tag_class(self, tag_class);
// ossl_asn1_set_indefinite_length(self, Qfalse);

// return self;
// }

static VALUE
to_der_internal(VALUE self, int constructed, int indef_len, VALUE body)
Expand Down Expand Up @@ -1110,20 +1110,20 @@ ossl_asn1_initialize(int argc, VALUE *argv, VALUE self)
return self;
}

static VALUE
ossl_asn1eoc_initialize(VALUE self) {
VALUE tag, tagging, tag_class, value;
tag = INT2FIX(0);
tagging = Qnil;
tag_class = sym_UNIVERSAL;
value = rb_str_new("", 0);
ossl_asn1_set_tag(self, tag);
ossl_asn1_set_value(self, value);
ossl_asn1_set_tagging(self, tagging);
ossl_asn1_set_tag_class(self, tag_class);
ossl_asn1_set_indefinite_length(self, Qfalse);
return self;
}
// static VALUE
// ossl_asn1eoc_initialize(VALUE self) {
// VALUE tag, tagging, tag_class, value;
// tag = INT2FIX(0);
// tagging = Qnil;
// tag_class = sym_UNIVERSAL;
// value = rb_str_new("", 0);
// ossl_asn1_set_tag(self, tag);
// ossl_asn1_set_value(self, value);
// ossl_asn1_set_tagging(self, tagging);
// ossl_asn1_set_tag_class(self, tag_class);
// ossl_asn1_set_indefinite_length(self, Qfalse);
// return self;
// }

static VALUE
ossl_asn1eoc_to_der(VALUE self)
Expand Down Expand Up @@ -1226,13 +1226,13 @@ ossl_asn1cons_to_der(VALUE self)
* puts asn1
* end
*/
static VALUE
ossl_asn1cons_each(VALUE self)
{
rb_block_call(ossl_asn1_get_value(self), id_each, 0, 0, 0, 0);
// static VALUE
// ossl_asn1cons_each(VALUE self)
// {
// rb_block_call(ossl_asn1_get_value(self), id_each, 0, 0, 0, 0);

return self;
}
// return self;
// }

/*
* call-seq:
Expand Down Expand Up @@ -1659,16 +1659,16 @@ Init_ossl_asn1(void)
* Please confer Constructive and Primitive for the mappings between
* ASN.1 data types and Ruby classes.
*/
rb_attr(cASN1Data, rb_intern("value"), 1, 1, 0);
// rb_attr(cASN1Data, rb_intern("value"), 1, 1, 0);
/*
* An Integer representing the tag number of this ASN1Data. Never +nil+.
*/
rb_attr(cASN1Data, rb_intern("tag"), 1, 1, 0);
// rb_attr(cASN1Data, rb_intern("tag"), 1, 1, 0);
/*
* A Symbol representing the tag class of this ASN1Data. Never +nil+.
* See ASN1Data for possible values.
*/
rb_attr(cASN1Data, rb_intern("tag_class"), 1, 1, 0);
// rb_attr(cASN1Data, rb_intern("tag_class"), 1, 1, 0);
/*
* Never +nil+. A boolean value indicating whether the encoding uses
* indefinite length (in the case of parsing) or whether an indefinite
Expand All @@ -1686,10 +1686,10 @@ Init_ossl_asn1(void)
* encoding, but also primitive types such as e.g. OCTET STRINGS or
* BIT STRINGS may leverage this functionality (cf. ITU-T X.690).
*/
rb_attr(cASN1Data, rb_intern("indefinite_length"), 1, 1, 0);
rb_define_alias(cASN1Data, "infinite_length", "indefinite_length");
rb_define_alias(cASN1Data, "infinite_length=", "indefinite_length=");
rb_define_method(cASN1Data, "initialize", ossl_asn1data_initialize, 3);
// rb_attr(cASN1Data, rb_intern("indefinite_length"), 1, 1, 0);
// rb_define_alias(cASN1Data, "infinite_length", "indefinite_length");
// rb_define_alias(cASN1Data, "infinite_length=", "indefinite_length=");
// rb_define_method(cASN1Data, "initialize", ossl_asn1data_initialize, 3);
rb_define_method(cASN1Data, "to_der", ossl_asn1data_to_der, 0);

/* Document-class: OpenSSL::ASN1::Primitive
Expand Down Expand Up @@ -1763,10 +1763,10 @@ Init_ossl_asn1(void)
* _tagging_ is not set when a ASN.1 structure is parsed using
* OpenSSL::ASN1.decode.
*/
rb_attr(cASN1Primitive, rb_intern("tagging"), 1, 1, Qtrue);
rb_undef_method(cASN1Primitive, "indefinite_length=");
rb_undef_method(cASN1Primitive, "infinite_length=");
rb_define_method(cASN1Primitive, "initialize", ossl_asn1_initialize, -1);
// rb_attr(cASN1Primitive, rb_intern("tagging"), 1, 1, Qtrue);
// rb_undef_method(cASN1Primitive, "indefinite_length=");
// rb_undef_method(cASN1Primitive, "infinite_length=");
// rb_define_method(cASN1Primitive, "initialize", ossl_asn1_initialize, -1);
rb_define_method(cASN1Primitive, "to_der", ossl_asn1prim_to_der, 0);

/* Document-class: OpenSSL::ASN1::Constructive
Expand Down Expand Up @@ -1797,17 +1797,17 @@ Init_ossl_asn1(void)
* set = OpenSSL::ASN1::Set.new( [ int, str ] )
*/
cASN1Constructive = rb_define_class_under(mASN1,"Constructive", cASN1Data);
rb_include_module(cASN1Constructive, rb_mEnumerable);
// rb_include_module(cASN1Constructive, rb_mEnumerable);
/*
* May be used as a hint for encoding a value either implicitly or
* explicitly by setting it either to +:IMPLICIT+ or to +:EXPLICIT+.
* _tagging_ is not set when a ASN.1 structure is parsed using
* OpenSSL::ASN1.decode.
*/
rb_attr(cASN1Constructive, rb_intern("tagging"), 1, 1, Qtrue);
rb_define_method(cASN1Constructive, "initialize", ossl_asn1_initialize, -1);
// rb_attr(cASN1Constructive, rb_intern("tagging"), 1, 1, Qtrue);
// rb_define_method(cASN1Constructive, "initialize", ossl_asn1_initialize, -1);
rb_define_method(cASN1Constructive, "to_der", ossl_asn1cons_to_der, 0);
rb_define_method(cASN1Constructive, "each", ossl_asn1cons_each, 0);
// rb_define_method(cASN1Constructive, "each", ossl_asn1cons_each, 0);

#define OSSL_ASN1_DEFINE_CLASS(name, super) \
do{\
Expand Down Expand Up @@ -1856,9 +1856,9 @@ do{\
rb_define_alias(cASN1ObjectId, "short_name", "sn");
rb_define_alias(cASN1ObjectId, "long_name", "ln");
rb_define_method(cASN1ObjectId, "==", ossl_asn1obj_eq, 1);
rb_attr(cASN1BitString, rb_intern("unused_bits"), 1, 1, 0);
// rb_attr(cASN1BitString, rb_intern("unused_bits"), 1, 1, 0);

rb_define_method(cASN1EndOfContent, "initialize", ossl_asn1eoc_initialize, 0);
// rb_define_method(cASN1EndOfContent, "initialize", ossl_asn1eoc_initialize, 0);
rb_define_method(cASN1EndOfContent, "to_der", ossl_asn1eoc_to_der, 0);

class_tag_map = rb_hash_new();
Expand Down Expand Up @@ -1886,6 +1886,7 @@ do{\
rb_hash_aset(class_tag_map, cASN1GeneralString, INT2NUM(V_ASN1_GENERALSTRING));
rb_hash_aset(class_tag_map, cASN1UniversalString, INT2NUM(V_ASN1_UNIVERSALSTRING));
rb_hash_aset(class_tag_map, cASN1BMPString, INT2NUM(V_ASN1_BMPSTRING));
rb_define_const(mASN1, "CLASS_TAG_MAP", class_tag_map);

id_each = rb_intern_const("each");
}
1 change: 1 addition & 0 deletions lib/openssl.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
require 'openssl.so'

require_relative 'openssl/bn'
require_relative 'openssl/asn1'
require_relative 'openssl/pkey'
require_relative 'openssl/cipher'
require_relative 'openssl/digest'
Expand Down
119 changes: 119 additions & 0 deletions lib/openssl/asn1.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
# frozen_string_literal: true
#--
#
# = Ruby-space definitions that completes C-space funcs for BN
#
# = Licence
# This program is licensed under the same licence as Ruby.
# (See the file 'LICENCE'.)
#++

module OpenSSL
module ASN1
class ASN1Data
attr_accessor :value, :tag, :tag_class

attr_reader :indefinite_length

def initialize(value, tag, tag_class)
raise ASN1Error, "invalid tag class" unless tag_class.is_a?(Symbol)

@tag = tag
@value = value
@tag_class = tag_class
@indefinite_length = false
end

def indefinite_length=(val)
@indefinite_length = val
end

alias infinite_length indefinite_length
alias infinite_length= indefinite_length=
end

class Primitive < ASN1Data
attr_accessor :tagging

undef_method :indefinite_length=
undef_method :infinite_length=

def initialize(value, tag = nil, tagging = nil, tag_class = nil)
tag ||= ASN1.take_default_tag(self.class)

raise ASN1Error, "must specify tag number" unless tag

if tagging
raise ASN1Error, "invalid tagging method" unless tagging.is_a?(Symbol)
end

tag_class ||= tagging ? :CONTEXT_SPECIFIC : :UNIVERSAL

raise ASN1Error, "invalid tag class" unless tag_class.is_a?(Symbol)

@tagging = tagging
super(value ,tag, tag_class)
end
end

class Constructive < ASN1Data
include Enumerable

attr_accessor :tagging

def initialize(value, tag = nil, tagging = nil, tag_class = nil)
tag ||= ASN1.take_default_tag(self.class)

raise ASN1Error, "must specify tag number" unless tag

if tagging
raise ASN1Error, "invalid tagging method" unless tagging.is_a?(Symbol)
end

tag_class ||= tagging ? :CONTEXT_SPECIFIC : :UNIVERSAL

raise ASN1Error, "invalid tag class" unless tag_class.is_a?(Symbol)

@tagging = tagging
super(value ,tag, tag_class)
end

def each(&blk)
@value.each(&blk)
end
end

class Boolean < Primitive ; end
class Integer < Primitive ; end
class Enumerated < Primitive ; end

class BitString < Primitive
attr_accessor :unused_bits

def initialize(*)
super

@unused_bits = 0
end
end

class EndOfContent < ASN1Data
def initialize
super("", 0, :UNIVERSAL)
end
end

# private
def self.take_default_tag(klass)
tag = CLASS_TAG_MAP[klass]

return tag if tag

sklass = klass.superclass

return unless sklass

take_default_tag(sklass)
end
end
end

0 comments on commit a492c19

Please sign in to comment.