Skip to content

Commit 655d144

Browse files
rewriting most of the asn1 init code in ruby
to have as much of the lib in ruby as possible
1 parent a8caa63 commit 655d144

File tree

4 files changed

+254
-207
lines changed

4 files changed

+254
-207
lines changed

ext/openssl/ossl_asn1.c

Lines changed: 23 additions & 207 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111

1212
static VALUE ossl_asn1_decode0(unsigned char **pp, long length, long *offset,
1313
int depth, int yield, long *num_read);
14-
static VALUE ossl_asn1_initialize(int argc, VALUE *argv, VALUE self);
1514

1615
/*
1716
* DATE conversion
@@ -638,35 +637,6 @@ ossl_asn1_class2sym(int tc)
638637
return sym_UNIVERSAL;
639638
}
640639

641-
/*
642-
* call-seq:
643-
* OpenSSL::ASN1::ASN1Data.new(value, tag, tag_class) => ASN1Data
644-
*
645-
* _value_: Please have a look at Constructive and Primitive to see how Ruby
646-
* types are mapped to ASN.1 types and vice versa.
647-
*
648-
* _tag_: An Integer indicating the tag number.
649-
*
650-
* _tag_class_: A Symbol indicating the tag class. Please cf. ASN1 for
651-
* possible values.
652-
*
653-
* == Example
654-
* asn1_int = OpenSSL::ASN1Data.new(42, 2, :UNIVERSAL) # => Same as OpenSSL::ASN1::Integer.new(42)
655-
* tagged_int = OpenSSL::ASN1Data.new(42, 0, :CONTEXT_SPECIFIC) # implicitly 0-tagged INTEGER
656-
*/
657-
static VALUE
658-
ossl_asn1data_initialize(VALUE self, VALUE value, VALUE tag, VALUE tag_class)
659-
{
660-
if(!SYMBOL_P(tag_class))
661-
ossl_raise(eASN1Error, "invalid tag class");
662-
ossl_asn1_set_tag(self, tag);
663-
ossl_asn1_set_value(self, value);
664-
ossl_asn1_set_tag_class(self, tag_class);
665-
ossl_asn1_set_indefinite_length(self, Qfalse);
666-
667-
return self;
668-
}
669-
670640
static VALUE
671641
to_der_internal(VALUE self, int constructed, int indef_len, VALUE body)
672642
{
@@ -795,20 +765,19 @@ int_ossl_asn1_decode0_prim(unsigned char **pp, long length, long hlen, int tag,
795765
if (tc == sym_UNIVERSAL &&
796766
tag < ossl_asn1_info_size && ossl_asn1_info[tag].klass) {
797767
VALUE klass = *ossl_asn1_info[tag].klass;
798-
VALUE args[4];
799-
args[0] = value;
800-
args[1] = INT2NUM(tag);
801-
args[2] = Qnil;
802-
args[3] = tc;
803-
asn1data = rb_obj_alloc(klass);
804-
ossl_asn1_initialize(4, args, asn1data);
768+
if (tag == V_ASN1_EOC)
769+
asn1data = rb_funcall(cASN1EndOfContent, rb_intern("new"), 0);
770+
else {
771+
VALUE args[4] = { value, INT2NUM(tag), Qnil, tc };
772+
asn1data = rb_funcall3(klass, rb_intern("new"), 4, args);
773+
}
805774
if(tag == V_ASN1_BIT_STRING){
806775
rb_ivar_set(asn1data, sivUNUSED_BITS, LONG2NUM(flag));
807776
}
808777
}
809778
else {
810-
asn1data = rb_obj_alloc(cASN1Data);
811-
ossl_asn1data_initialize(asn1data, value, INT2NUM(tag), tc);
779+
VALUE args[3] = { value, INT2NUM(tag), tc };
780+
asn1data = rb_funcall3(cASN1Data, rb_intern("new"), 3, args);
812781
}
813782

814783
return asn1data;
@@ -842,20 +811,22 @@ int_ossl_asn1_decode0_cons(unsigned char **pp, long max_len, long length,
842811
}
843812

844813
if (tc == sym_UNIVERSAL) {
845-
VALUE args[4];
846-
if (tag == V_ASN1_SEQUENCE || tag == V_ASN1_SET)
847-
asn1data = rb_obj_alloc(*ossl_asn1_info[tag].klass);
848-
else
849-
asn1data = rb_obj_alloc(cASN1Constructive);
850-
args[0] = ary;
851-
args[1] = INT2NUM(tag);
852-
args[2] = Qnil;
853-
args[3] = tc;
854-
ossl_asn1_initialize(4, args, asn1data);
814+
if (tag == V_ASN1_EOC)
815+
asn1data = rb_funcall(cASN1EndOfContent, rb_intern("new"), 0);
816+
else if (tag == V_ASN1_SEQUENCE) {
817+
VALUE args[4] = { ary, INT2NUM(tag), Qnil, tc };
818+
asn1data = rb_funcall3(cASN1Sequence, rb_intern("new"), 4, args);
819+
} else if (tag == V_ASN1_SET) {
820+
VALUE args[4] = { ary, INT2NUM(tag), Qnil, tc };
821+
asn1data = rb_funcall3(cASN1Set, rb_intern("new"), 4, args);
822+
} else {
823+
VALUE args[4] = { ary, INT2NUM(tag), Qnil, tc };
824+
asn1data = rb_funcall3(cASN1Constructive, rb_intern("new"), 4, args);
825+
}
855826
}
856827
else {
857-
asn1data = rb_obj_alloc(cASN1Data);
858-
ossl_asn1data_initialize(asn1data, ary, INT2NUM(tag), tc);
828+
VALUE args[3] = {ary, INT2NUM(tag), tc};
829+
asn1data = rb_funcall3(cASN1Data, rb_intern("new"), 3, args);
859830
}
860831

861832
if (indefinite)
@@ -1048,83 +1019,6 @@ ossl_asn1_decode_all(VALUE self, VALUE obj)
10481019
return ary;
10491020
}
10501021

1051-
/*
1052-
* call-seq:
1053-
* OpenSSL::ASN1::Primitive.new(value [, tag, tagging, tag_class ]) => Primitive
1054-
*
1055-
* _value_: is mandatory.
1056-
*
1057-
* _tag_: optional, may be specified for tagged values. If no _tag_ is
1058-
* specified, the UNIVERSAL tag corresponding to the Primitive sub-class
1059-
* is used by default.
1060-
*
1061-
* _tagging_: may be used as an encoding hint to encode a value either
1062-
* explicitly or implicitly, see ASN1 for possible values.
1063-
*
1064-
* _tag_class_: if _tag_ and _tagging_ are +nil+ then this is set to
1065-
* +:UNIVERSAL+ by default. If either _tag_ or _tagging_ are set then
1066-
* +:CONTEXT_SPECIFIC+ is used as the default. For possible values please
1067-
* cf. ASN1.
1068-
*
1069-
* == Example
1070-
* int = OpenSSL::ASN1::Integer.new(42)
1071-
* zero_tagged_int = OpenSSL::ASN1::Integer.new(42, 0, :IMPLICIT)
1072-
* private_explicit_zero_tagged_int = OpenSSL::ASN1::Integer.new(42, 0, :EXPLICIT, :PRIVATE)
1073-
*/
1074-
static VALUE
1075-
ossl_asn1_initialize(int argc, VALUE *argv, VALUE self)
1076-
{
1077-
VALUE value, tag, tagging, tag_class;
1078-
int default_tag;
1079-
1080-
rb_scan_args(argc, argv, "13", &value, &tag, &tagging, &tag_class);
1081-
default_tag = ossl_asn1_default_tag(self);
1082-
1083-
if (default_tag == -1 || argc > 1) {
1084-
if(NIL_P(tag))
1085-
ossl_raise(eASN1Error, "must specify tag number");
1086-
if(!NIL_P(tagging) && !SYMBOL_P(tagging))
1087-
ossl_raise(eASN1Error, "invalid tagging method");
1088-
if(NIL_P(tag_class)) {
1089-
if (NIL_P(tagging))
1090-
tag_class = sym_UNIVERSAL;
1091-
else
1092-
tag_class = sym_CONTEXT_SPECIFIC;
1093-
}
1094-
if(!SYMBOL_P(tag_class))
1095-
ossl_raise(eASN1Error, "invalid tag class");
1096-
}
1097-
else{
1098-
tag = INT2NUM(default_tag);
1099-
tagging = Qnil;
1100-
tag_class = sym_UNIVERSAL;
1101-
}
1102-
ossl_asn1_set_tag(self, tag);
1103-
ossl_asn1_set_value(self, value);
1104-
ossl_asn1_set_tagging(self, tagging);
1105-
ossl_asn1_set_tag_class(self, tag_class);
1106-
ossl_asn1_set_indefinite_length(self, Qfalse);
1107-
if (default_tag == V_ASN1_BIT_STRING)
1108-
rb_ivar_set(self, sivUNUSED_BITS, INT2FIX(0));
1109-
1110-
return self;
1111-
}
1112-
1113-
static VALUE
1114-
ossl_asn1eoc_initialize(VALUE self) {
1115-
VALUE tag, tagging, tag_class, value;
1116-
tag = INT2FIX(0);
1117-
tagging = Qnil;
1118-
tag_class = sym_UNIVERSAL;
1119-
value = rb_str_new("", 0);
1120-
ossl_asn1_set_tag(self, tag);
1121-
ossl_asn1_set_value(self, value);
1122-
ossl_asn1_set_tagging(self, tagging);
1123-
ossl_asn1_set_tag_class(self, tag_class);
1124-
ossl_asn1_set_indefinite_length(self, Qfalse);
1125-
return self;
1126-
}
1127-
11281022
static VALUE
11291023
ossl_asn1eoc_to_der(VALUE self)
11301024
{
@@ -1213,27 +1107,6 @@ ossl_asn1cons_to_der(VALUE self)
12131107
return to_der_internal(self, 1, indef_len, str);
12141108
}
12151109

1216-
/*
1217-
* call-seq:
1218-
* asn1_ary.each { |asn1| block } => asn1_ary
1219-
*
1220-
* Calls the given block once for each element in self, passing that element
1221-
* as parameter _asn1_. If no block is given, an enumerator is returned
1222-
* instead.
1223-
*
1224-
* == Example
1225-
* asn1_ary.each do |asn1|
1226-
* puts asn1
1227-
* end
1228-
*/
1229-
static VALUE
1230-
ossl_asn1cons_each(VALUE self)
1231-
{
1232-
rb_block_call(ossl_asn1_get_value(self), id_each, 0, 0, 0, 0);
1233-
1234-
return self;
1235-
}
1236-
12371110
/*
12381111
* call-seq:
12391112
* OpenSSL::ASN1::ObjectId.register(object_id, short_name, long_name)
@@ -1654,42 +1527,6 @@ Init_ossl_asn1(void)
16541527
* puts int2.value # => 1
16551528
*/
16561529
cASN1Data = rb_define_class_under(mASN1, "ASN1Data", rb_cObject);
1657-
/*
1658-
* Carries the value of a ASN.1 type.
1659-
* Please confer Constructive and Primitive for the mappings between
1660-
* ASN.1 data types and Ruby classes.
1661-
*/
1662-
rb_attr(cASN1Data, rb_intern("value"), 1, 1, 0);
1663-
/*
1664-
* An Integer representing the tag number of this ASN1Data. Never +nil+.
1665-
*/
1666-
rb_attr(cASN1Data, rb_intern("tag"), 1, 1, 0);
1667-
/*
1668-
* A Symbol representing the tag class of this ASN1Data. Never +nil+.
1669-
* See ASN1Data for possible values.
1670-
*/
1671-
rb_attr(cASN1Data, rb_intern("tag_class"), 1, 1, 0);
1672-
/*
1673-
* Never +nil+. A boolean value indicating whether the encoding uses
1674-
* indefinite length (in the case of parsing) or whether an indefinite
1675-
* length form shall be used (in the encoding case).
1676-
* In DER, every value uses definite length form. But in scenarios where
1677-
* large amounts of data need to be transferred it might be desirable to
1678-
* have some kind of streaming support available.
1679-
* For example, huge OCTET STRINGs are preferably sent in smaller-sized
1680-
* chunks, each at a time.
1681-
* This is possible in BER by setting the length bytes of an encoding
1682-
* to zero and by this indicating that the following value will be
1683-
* sent in chunks. Indefinite length encodings are always constructed.
1684-
* The end of such a stream of chunks is indicated by sending a EOC
1685-
* (End of Content) tag. SETs and SEQUENCEs may use an indefinite length
1686-
* encoding, but also primitive types such as e.g. OCTET STRINGS or
1687-
* BIT STRINGS may leverage this functionality (cf. ITU-T X.690).
1688-
*/
1689-
rb_attr(cASN1Data, rb_intern("indefinite_length"), 1, 1, 0);
1690-
rb_define_alias(cASN1Data, "infinite_length", "indefinite_length");
1691-
rb_define_alias(cASN1Data, "infinite_length=", "indefinite_length=");
1692-
rb_define_method(cASN1Data, "initialize", ossl_asn1data_initialize, 3);
16931530
rb_define_method(cASN1Data, "to_der", ossl_asn1data_to_der, 0);
16941531

16951532
/* Document-class: OpenSSL::ASN1::Primitive
@@ -1757,16 +1594,6 @@ Init_ossl_asn1(void)
17571594
* prim_zero_tagged_explicit = <class>.new(value, 0, :EXPLICIT)
17581595
*/
17591596
cASN1Primitive = rb_define_class_under(mASN1, "Primitive", cASN1Data);
1760-
/*
1761-
* May be used as a hint for encoding a value either implicitly or
1762-
* explicitly by setting it either to +:IMPLICIT+ or to +:EXPLICIT+.
1763-
* _tagging_ is not set when a ASN.1 structure is parsed using
1764-
* OpenSSL::ASN1.decode.
1765-
*/
1766-
rb_attr(cASN1Primitive, rb_intern("tagging"), 1, 1, Qtrue);
1767-
rb_undef_method(cASN1Primitive, "indefinite_length=");
1768-
rb_undef_method(cASN1Primitive, "infinite_length=");
1769-
rb_define_method(cASN1Primitive, "initialize", ossl_asn1_initialize, -1);
17701597
rb_define_method(cASN1Primitive, "to_der", ossl_asn1prim_to_der, 0);
17711598

17721599
/* Document-class: OpenSSL::ASN1::Constructive
@@ -1797,17 +1624,7 @@ Init_ossl_asn1(void)
17971624
* set = OpenSSL::ASN1::Set.new( [ int, str ] )
17981625
*/
17991626
cASN1Constructive = rb_define_class_under(mASN1,"Constructive", cASN1Data);
1800-
rb_include_module(cASN1Constructive, rb_mEnumerable);
1801-
/*
1802-
* May be used as a hint for encoding a value either implicitly or
1803-
* explicitly by setting it either to +:IMPLICIT+ or to +:EXPLICIT+.
1804-
* _tagging_ is not set when a ASN.1 structure is parsed using
1805-
* OpenSSL::ASN1.decode.
1806-
*/
1807-
rb_attr(cASN1Constructive, rb_intern("tagging"), 1, 1, Qtrue);
1808-
rb_define_method(cASN1Constructive, "initialize", ossl_asn1_initialize, -1);
18091627
rb_define_method(cASN1Constructive, "to_der", ossl_asn1cons_to_der, 0);
1810-
rb_define_method(cASN1Constructive, "each", ossl_asn1cons_each, 0);
18111628

18121629
#define OSSL_ASN1_DEFINE_CLASS(name, super) \
18131630
do{\
@@ -1856,9 +1673,7 @@ do{\
18561673
rb_define_alias(cASN1ObjectId, "short_name", "sn");
18571674
rb_define_alias(cASN1ObjectId, "long_name", "ln");
18581675
rb_define_method(cASN1ObjectId, "==", ossl_asn1obj_eq, 1);
1859-
rb_attr(cASN1BitString, rb_intern("unused_bits"), 1, 1, 0);
18601676

1861-
rb_define_method(cASN1EndOfContent, "initialize", ossl_asn1eoc_initialize, 0);
18621677
rb_define_method(cASN1EndOfContent, "to_der", ossl_asn1eoc_to_der, 0);
18631678

18641679
class_tag_map = rb_hash_new();
@@ -1886,6 +1701,7 @@ do{\
18861701
rb_hash_aset(class_tag_map, cASN1GeneralString, INT2NUM(V_ASN1_GENERALSTRING));
18871702
rb_hash_aset(class_tag_map, cASN1UniversalString, INT2NUM(V_ASN1_UNIVERSALSTRING));
18881703
rb_hash_aset(class_tag_map, cASN1BMPString, INT2NUM(V_ASN1_BMPSTRING));
1704+
rb_define_const(mASN1, "CLASS_TAG_MAP", class_tag_map);
18891705

18901706
id_each = rb_intern_const("each");
18911707
}

ext/openssl/ossl_asn1.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ extern VALUE cASN1ObjectId; /* OBJECT IDENTIFIER */
5555
extern VALUE cASN1UTCTime, cASN1GeneralizedTime; /* TIME */
5656
extern VALUE cASN1Sequence, cASN1Set; /* CONSTRUCTIVE */
5757

58+
extern VALUE cASN1EndOfContent; /* END OF CONTENT */
59+
5860
ASN1_TYPE *ossl_asn1_get_asn1type(VALUE);
5961

6062
void Init_ossl_asn1(void);

lib/openssl.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
require 'openssl.so'
1414

1515
require_relative 'openssl/bn'
16+
require_relative 'openssl/asn1'
1617
require_relative 'openssl/pkey'
1718
require_relative 'openssl/cipher'
1819
require_relative 'openssl/digest'

0 commit comments

Comments
 (0)