Skip to content

Commit 8305051

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

File tree

4 files changed

+213
-216
lines changed

4 files changed

+213
-216
lines changed

ext/openssl/ossl_asn1.c

Lines changed: 22 additions & 216 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
@@ -158,10 +157,6 @@ asn1integer_to_num_i(VALUE arg)
158157
#define ossl_asn1_get_tag_class(o) rb_attr_get((o),sivTAG_CLASS)
159158
#define ossl_asn1_get_indefinite_length(o) rb_attr_get((o),sivINDEFINITE_LENGTH)
160159

161-
#define ossl_asn1_set_value(o,v) rb_ivar_set((o),sivVALUE,(v))
162-
#define ossl_asn1_set_tag(o,v) rb_ivar_set((o),sivTAG,(v))
163-
#define ossl_asn1_set_tagging(o,v) rb_ivar_set((o),sivTAGGING,(v))
164-
#define ossl_asn1_set_tag_class(o,v) rb_ivar_set((o),sivTAG_CLASS,(v))
165160
#define ossl_asn1_set_indefinite_length(o,v) rb_ivar_set((o),sivINDEFINITE_LENGTH,(v))
166161

167162
VALUE mASN1;
@@ -189,7 +184,6 @@ VALUE cASN1Sequence, cASN1Set; /* CONSTRUCTIVE */
189184
static VALUE sym_IMPLICIT, sym_EXPLICIT;
190185
static VALUE sym_UNIVERSAL, sym_APPLICATION, sym_CONTEXT_SPECIFIC, sym_PRIVATE;
191186
static ID sivVALUE, sivTAG, sivTAG_CLASS, sivTAGGING, sivINDEFINITE_LENGTH, sivUNUSED_BITS;
192-
static ID id_each;
193187

194188
/*
195189
* Ruby to ASN1 converters
@@ -638,35 +632,6 @@ ossl_asn1_class2sym(int tc)
638632
return sym_UNIVERSAL;
639633
}
640634

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-
670635
static VALUE
671636
to_der_internal(VALUE self, int constructed, int indef_len, VALUE body)
672637
{
@@ -795,20 +760,19 @@ int_ossl_asn1_decode0_prim(unsigned char **pp, long length, long hlen, int tag,
795760
if (tc == sym_UNIVERSAL &&
796761
tag < ossl_asn1_info_size && ossl_asn1_info[tag].klass) {
797762
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);
763+
if (tag == V_ASN1_EOC)
764+
asn1data = rb_funcall(cASN1EndOfContent, rb_intern("new"), 0);
765+
else {
766+
VALUE args[4] = { value, INT2NUM(tag), Qnil, tc };
767+
asn1data = rb_funcallv_public(klass, rb_intern("new"), 4, args);
768+
}
805769
if(tag == V_ASN1_BIT_STRING){
806770
rb_ivar_set(asn1data, sivUNUSED_BITS, LONG2NUM(flag));
807771
}
808772
}
809773
else {
810-
asn1data = rb_obj_alloc(cASN1Data);
811-
ossl_asn1data_initialize(asn1data, value, INT2NUM(tag), tc);
774+
VALUE args[3] = { value, INT2NUM(tag), tc };
775+
asn1data = rb_funcallv_public(cASN1Data, rb_intern("new"), 3, args);
812776
}
813777

814778
return asn1data;
@@ -842,20 +806,20 @@ int_ossl_asn1_decode0_cons(unsigned char **pp, long max_len, long length,
842806
}
843807

844808
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);
809+
if (tag == V_ASN1_SEQUENCE) {
810+
VALUE args[4] = { ary, INT2NUM(tag), Qnil, tc };
811+
asn1data = rb_funcallv_public(cASN1Sequence, rb_intern("new"), 4, args);
812+
} else if (tag == V_ASN1_SET) {
813+
VALUE args[4] = { ary, INT2NUM(tag), Qnil, tc };
814+
asn1data = rb_funcallv_public(cASN1Set, rb_intern("new"), 4, args);
815+
} else {
816+
VALUE args[4] = { ary, INT2NUM(tag), Qnil, tc };
817+
asn1data = rb_funcallv_public(cASN1Constructive, rb_intern("new"), 4, args);
818+
}
855819
}
856820
else {
857-
asn1data = rb_obj_alloc(cASN1Data);
858-
ossl_asn1data_initialize(asn1data, ary, INT2NUM(tag), tc);
821+
VALUE args[3] = {ary, INT2NUM(tag), tc};
822+
asn1data = rb_funcallv_public(cASN1Data, rb_intern("new"), 3, args);
859823
}
860824

861825
if (indefinite)
@@ -1048,83 +1012,6 @@ ossl_asn1_decode_all(VALUE self, VALUE obj)
10481012
return ary;
10491013
}
10501014

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-
11281015
static VALUE
11291016
ossl_asn1eoc_to_der(VALUE self)
11301017
{
@@ -1216,27 +1103,6 @@ ossl_asn1cons_to_der(VALUE self)
12161103
return to_der_internal(self, 1, indef_len, str);
12171104
}
12181105

1219-
/*
1220-
* call-seq:
1221-
* asn1_ary.each { |asn1| block } => asn1_ary
1222-
*
1223-
* Calls the given block once for each element in self, passing that element
1224-
* as parameter _asn1_. If no block is given, an enumerator is returned
1225-
* instead.
1226-
*
1227-
* == Example
1228-
* asn1_ary.each do |asn1|
1229-
* puts asn1
1230-
* end
1231-
*/
1232-
static VALUE
1233-
ossl_asn1cons_each(VALUE self)
1234-
{
1235-
rb_block_call(ossl_asn1_get_value(self), id_each, 0, 0, 0, 0);
1236-
1237-
return self;
1238-
}
1239-
12401106
/*
12411107
* call-seq:
12421108
* OpenSSL::ASN1::ObjectId.register(object_id, short_name, long_name)
@@ -1371,7 +1237,7 @@ ossl_asn1obj_get_oid(VALUE self)
13711237

13721238
#define OSSL_ASN1_IMPL_FACTORY_METHOD(klass) \
13731239
static VALUE ossl_asn1_##klass(int argc, VALUE *argv, VALUE self)\
1374-
{ return rb_funcall3(cASN1##klass, rb_intern("new"), argc, argv); }
1240+
{ return rb_funcallv_public(cASN1##klass, rb_intern("new"), argc, argv); }
13751241

13761242
OSSL_ASN1_IMPL_FACTORY_METHOD(Boolean)
13771243
OSSL_ASN1_IMPL_FACTORY_METHOD(Integer)
@@ -1657,42 +1523,6 @@ Init_ossl_asn1(void)
16571523
* puts int2.value # => 1
16581524
*/
16591525
cASN1Data = rb_define_class_under(mASN1, "ASN1Data", rb_cObject);
1660-
/*
1661-
* Carries the value of a ASN.1 type.
1662-
* Please confer Constructive and Primitive for the mappings between
1663-
* ASN.1 data types and Ruby classes.
1664-
*/
1665-
rb_attr(cASN1Data, rb_intern("value"), 1, 1, 0);
1666-
/*
1667-
* An Integer representing the tag number of this ASN1Data. Never +nil+.
1668-
*/
1669-
rb_attr(cASN1Data, rb_intern("tag"), 1, 1, 0);
1670-
/*
1671-
* A Symbol representing the tag class of this ASN1Data. Never +nil+.
1672-
* See ASN1Data for possible values.
1673-
*/
1674-
rb_attr(cASN1Data, rb_intern("tag_class"), 1, 1, 0);
1675-
/*
1676-
* Never +nil+. A boolean value indicating whether the encoding uses
1677-
* indefinite length (in the case of parsing) or whether an indefinite
1678-
* length form shall be used (in the encoding case).
1679-
* In DER, every value uses definite length form. But in scenarios where
1680-
* large amounts of data need to be transferred it might be desirable to
1681-
* have some kind of streaming support available.
1682-
* For example, huge OCTET STRINGs are preferably sent in smaller-sized
1683-
* chunks, each at a time.
1684-
* This is possible in BER by setting the length bytes of an encoding
1685-
* to zero and by this indicating that the following value will be
1686-
* sent in chunks. Indefinite length encodings are always constructed.
1687-
* The end of such a stream of chunks is indicated by sending a EOC
1688-
* (End of Content) tag. SETs and SEQUENCEs may use an indefinite length
1689-
* encoding, but also primitive types such as e.g. OCTET STRINGS or
1690-
* BIT STRINGS may leverage this functionality (cf. ITU-T X.690).
1691-
*/
1692-
rb_attr(cASN1Data, rb_intern("indefinite_length"), 1, 1, 0);
1693-
rb_define_alias(cASN1Data, "infinite_length", "indefinite_length");
1694-
rb_define_alias(cASN1Data, "infinite_length=", "indefinite_length=");
1695-
rb_define_method(cASN1Data, "initialize", ossl_asn1data_initialize, 3);
16961526
rb_define_method(cASN1Data, "to_der", ossl_asn1data_to_der, 0);
16971527

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

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

18151625
#define OSSL_ASN1_DEFINE_CLASS(name, super) \
18161626
do{\
@@ -1859,13 +1669,10 @@ do{\
18591669
rb_define_alias(cASN1ObjectId, "short_name", "sn");
18601670
rb_define_alias(cASN1ObjectId, "long_name", "ln");
18611671
rb_define_method(cASN1ObjectId, "==", ossl_asn1obj_eq, 1);
1862-
rb_attr(cASN1BitString, rb_intern("unused_bits"), 1, 1, 0);
18631672

1864-
rb_define_method(cASN1EndOfContent, "initialize", ossl_asn1eoc_initialize, 0);
18651673
rb_define_method(cASN1EndOfContent, "to_der", ossl_asn1eoc_to_der, 0);
18661674

18671675
class_tag_map = rb_hash_new();
1868-
rb_gc_register_mark_object(class_tag_map);
18691676
rb_hash_aset(class_tag_map, cASN1EndOfContent, INT2NUM(V_ASN1_EOC));
18701677
rb_hash_aset(class_tag_map, cASN1Boolean, INT2NUM(V_ASN1_BOOLEAN));
18711678
rb_hash_aset(class_tag_map, cASN1Integer, INT2NUM(V_ASN1_INTEGER));
@@ -1889,6 +1696,5 @@ do{\
18891696
rb_hash_aset(class_tag_map, cASN1GeneralString, INT2NUM(V_ASN1_GENERALSTRING));
18901697
rb_hash_aset(class_tag_map, cASN1UniversalString, INT2NUM(V_ASN1_UNIVERSALSTRING));
18911698
rb_hash_aset(class_tag_map, cASN1BMPString, INT2NUM(V_ASN1_BMPSTRING));
1892-
1893-
id_each = rb_intern_const("each");
1699+
rb_define_const(mASN1, "CLASS_TAG_MAP", class_tag_map);
18941700
}

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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy