Skip to content

Commit b82ba18

Browse files
committed
* ext/openssl/ossl_asn1.c: indefinite length BER to DER encoding is
properly supported. Thanks Martin Bosslet! [ruby-core:33082] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@30178 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
1 parent 5e14eeb commit b82ba18

File tree

3 files changed

+352
-27
lines changed

3 files changed

+352
-27
lines changed

ChangeLog

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
Sun Dec 12 02:42:24 2010 Aaron Patterson <[email protected]>
2+
3+
* ext/openssl/ossl_asn1.c: indefinite length BER to DER encoding is
4+
properly supported. Thanks Martin Bosslet! [ruby-core:33082]
5+
16
Sat Dec 11 17:43:34 2010 Kazuhiro NISHIYAMA <[email protected]>
27

38
* ext/bigdecimal/bigdecimal.h: suppress "warning: 'VPrint' declared

ext/openssl/ossl_asn1.c

Lines changed: 120 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ struct timeval {
1919
};
2020
#endif
2121

22+
static VALUE join_der(VALUE enumerable);
23+
2224
/*
2325
* DATE conversion
2426
*/
@@ -156,15 +158,17 @@ num_to_asn1integer(VALUE obj, ASN1_INTEGER *ai)
156158
/*
157159
* ASN1 module
158160
*/
159-
#define ossl_asn1_get_value(o) rb_attr_get((o),rb_intern("@value"))
160-
#define ossl_asn1_get_tag(o) rb_attr_get((o),rb_intern("@tag"))
161-
#define ossl_asn1_get_tagging(o) rb_attr_get((o),rb_intern("@tagging"))
162-
#define ossl_asn1_get_tag_class(o) rb_attr_get((o),rb_intern("@tag_class"))
163-
164-
#define ossl_asn1_set_value(o,v) rb_iv_set((o),"@value",(v))
165-
#define ossl_asn1_set_tag(o,v) rb_iv_set((o),"@tag",(v))
166-
#define ossl_asn1_set_tagging(o,v) rb_iv_set((o),"@tagging",(v))
167-
#define ossl_asn1_set_tag_class(o,v) rb_iv_set((o),"@tag_class",(v))
161+
#define ossl_asn1_get_value(o) rb_attr_get((o),rb_intern("@value"))
162+
#define ossl_asn1_get_tag(o) rb_attr_get((o),rb_intern("@tag"))
163+
#define ossl_asn1_get_tagging(o) rb_attr_get((o),rb_intern("@tagging"))
164+
#define ossl_asn1_get_tag_class(o) rb_attr_get((o),rb_intern("@tag_class"))
165+
#define ossl_asn1_get_infinite_length(o) rb_attr_get((o),rb_intern("@infinite_length"))
166+
167+
#define ossl_asn1_set_value(o,v) rb_iv_set((o),"@value",(v))
168+
#define ossl_asn1_set_tag(o,v) rb_iv_set((o),"@tag",(v))
169+
#define ossl_asn1_set_tagging(o,v) rb_iv_set((o),"@tagging",(v))
170+
#define ossl_asn1_set_tag_class(o,v) rb_iv_set((o),"@tag_class",(v))
171+
#define ossl_asn1_set_infinite_length(o,v) rb_iv_set((o),"@infinite_length",(v))
168172

169173
VALUE mASN1;
170174
VALUE eASN1Error;
@@ -173,6 +177,7 @@ VALUE cASN1Data;
173177
VALUE cASN1Primitive;
174178
VALUE cASN1Constructive;
175179

180+
VALUE cASN1EndOfContent;
176181
VALUE cASN1Boolean; /* BOOLEAN */
177182
VALUE cASN1Integer, cASN1Enumerated; /* INTEGER */
178183
VALUE cASN1BitString; /* BIT STRING */
@@ -449,7 +454,7 @@ typedef struct {
449454
} ossl_asn1_info_t;
450455

451456
static ossl_asn1_info_t ossl_asn1_info[] = {
452-
{ "EOC", NULL, }, /* 0 */
457+
{ "EOC", &cASN1EndOfContent, }, /* 0 */
453458
{ "BOOLEAN", &cASN1Boolean, }, /* 1 */
454459
{ "INTEGER", &cASN1Integer, }, /* 2 */
455460
{ "BIT_STRING", &cASN1BitString, }, /* 3 */
@@ -660,6 +665,7 @@ ossl_asn1data_initialize(VALUE self, VALUE value, VALUE tag, VALUE tag_class)
660665
ossl_asn1_set_tag(self, tag);
661666
ossl_asn1_set_value(self, value);
662667
ossl_asn1_set_tag_class(self, tag_class);
668+
ossl_asn1_set_infinite_length(self, Qfalse);
663669

664670
return self;
665671
}
@@ -684,8 +690,8 @@ join_der(VALUE enumerable)
684690
static VALUE
685691
ossl_asn1data_to_der(VALUE self)
686692
{
687-
VALUE value, der;
688-
int tag, tag_class, is_cons = 0;
693+
VALUE value, der, inf_length;
694+
int tag, tag_class, is_cons = 0, tmp_cons = 1;
689695
long length;
690696
unsigned char *p;
691697

@@ -698,7 +704,12 @@ ossl_asn1data_to_der(VALUE self)
698704

699705
tag = ossl_asn1_tag(self);
700706
tag_class = ossl_asn1_tag_class(self);
701-
if((length = ASN1_object_size(1, RSTRING_LEN(value), tag)) <= 0)
707+
inf_length = ossl_asn1_get_infinite_length(self);
708+
if (inf_length == Qtrue) {
709+
is_cons = 2;
710+
tmp_cons = 2;
711+
}
712+
if((length = ASN1_object_size(tmp_cons, RSTRING_LEN(value), tag)) <= 0)
702713
ossl_raise(eASN1Error, NULL);
703714
der = rb_str_new(0, length);
704715
p = (unsigned char *)RSTRING_PTR(der);
@@ -717,7 +728,7 @@ ossl_asn1_decode0(unsigned char **pp, long length, long *offset, long depth,
717728
unsigned char *start, *p;
718729
const unsigned char *p0;
719730
long len, off = *offset;
720-
int hlen, tag, tc, j;
731+
int hlen, tag, tc, j, infinite = 0;
721732
VALUE ary, asn1data, value, tag_class;
722733

723734
ary = rb_ary_new();
@@ -752,8 +763,8 @@ ossl_asn1_decode0(unsigned char **pp, long length, long *offset, long depth,
752763
else
753764
tag_class = sUNIVERSAL;
754765
if(j & V_ASN1_CONSTRUCTED){
755-
/* TODO: if j == 0x21 it is indefinite length object. */
756766
if((j == 0x21) && (len == 0)){
767+
infinite = 1;
757768
long lastoff = off;
758769
value = ossl_asn1_decode0(&p, length, &off, depth+1, 0, yield);
759770
len = off - lastoff;
@@ -798,15 +809,39 @@ ossl_asn1_decode0(unsigned char **pp, long length, long *offset, long depth,
798809
break;
799810
}
800811
}
801-
asn1data = rb_funcall(klass, rb_intern("new"), 1, value);
812+
if (infinite && !(tag == V_ASN1_SEQUENCE || tag == V_ASN1_SET)){
813+
asn1data = rb_funcall(cASN1Constructive,
814+
rb_intern("new"),
815+
4,
816+
value,
817+
INT2NUM(tag),
818+
Qnil,
819+
ID2SYM(tag_class));
820+
}
821+
else{
822+
if (tag == V_ASN1_EOC){
823+
asn1data = rb_funcall(cASN1EndOfContent,
824+
rb_intern("new"),
825+
0);
826+
}
827+
else{
828+
asn1data = rb_funcall(klass, rb_intern("new"), 1, value);
829+
}
830+
}
802831
if(tag == V_ASN1_BIT_STRING){
803832
rb_iv_set(asn1data, "@unused_bits", LONG2NUM(flag));
804833
}
805834
}
806835
else{
807-
asn1data = rb_funcall(cASN1Data, rb_intern("new"), 3,
836+
asn1data = rb_funcall(cASN1Data, rb_intern("new"), 3,
808837
value, INT2NUM(tag), ID2SYM(tag_class));
809-
}
838+
}
839+
840+
if (infinite)
841+
ossl_asn1_set_infinite_length(asn1data, Qtrue);
842+
else
843+
ossl_asn1_set_infinite_length(asn1data, Qfalse);
844+
810845
rb_ary_push(ary, asn1data);
811846
length -= len;
812847
if(once) break;
@@ -894,10 +929,26 @@ ossl_asn1_initialize(int argc, VALUE *argv, VALUE self)
894929
ossl_asn1_set_value(self, value);
895930
ossl_asn1_set_tagging(self, tagging);
896931
ossl_asn1_set_tag_class(self, tag_class);
932+
ossl_asn1_set_infinite_length(self, Qfalse);
897933

898934
return self;
899935
}
900936

937+
static VALUE
938+
ossl_asn1eoc_initialize(VALUE self) {
939+
VALUE tag, tagging, tag_class, value;
940+
tag = INT2NUM(ossl_asn1_default_tag(self));
941+
tagging = Qnil;
942+
tag_class = ID2SYM(sUNIVERSAL);
943+
value = rb_str_new("", 0);
944+
ossl_asn1_set_tag(self, tag);
945+
ossl_asn1_set_value(self, value);
946+
ossl_asn1_set_tagging(self, tagging);
947+
ossl_asn1_set_tag_class(self, tag_class);
948+
ossl_asn1_set_infinite_length(self, Qfalse);
949+
return self;
950+
}
951+
901952
static int
902953
ossl_i2d_ASN1_TYPE(ASN1_TYPE *a, unsigned char **pp)
903954
{
@@ -962,29 +1013,64 @@ ossl_asn1prim_to_der(VALUE self)
9621013
static VALUE
9631014
ossl_asn1cons_to_der(VALUE self)
9641015
{
965-
int tag, tn, tc, explicit;
1016+
int tag, tn, tc, explicit, constructed = 1;
1017+
int found_prim = 0;
9661018
long seq_len, length;
9671019
unsigned char *p;
968-
VALUE value, str;
1020+
VALUE value, str, inf_length, ary, example;
9691021

970-
tag = ossl_asn1_default_tag(self);
9711022
tn = NUM2INT(ossl_asn1_get_tag(self));
9721023
tc = ossl_asn1_tag_class(self);
1024+
inf_length = ossl_asn1_get_infinite_length(self);
1025+
if (inf_length == Qtrue) {
1026+
constructed = 2;
1027+
if (CLASS_OF(self) == cASN1Sequence ||
1028+
CLASS_OF(self) == cASN1Set) {
1029+
tag = ossl_asn1_default_tag(self);
1030+
}
1031+
else { /*BIT_STRING OR OCTET_STRING*/
1032+
ary = ossl_asn1_get_value(self);
1033+
/* Recursively descend until a primitive value is found.
1034+
The overall value of the entire constructed encoding
1035+
is of the type of the first primitive encoding to be
1036+
found. */
1037+
while (!found_prim){
1038+
example = rb_ary_entry(ary, 0);
1039+
if (rb_obj_is_kind_of(example, cASN1Primitive)){
1040+
found_prim = 1;
1041+
}
1042+
else {
1043+
/* example is another ASN1Constructive */
1044+
if (!rb_obj_is_kind_of(example, cASN1Constructive)){
1045+
ossl_raise(eASN1Error, "invalid constructed encoding");
1046+
return Qnil; /* dummy */
1047+
}
1048+
ary = ossl_asn1_get_value(example);
1049+
}
1050+
}
1051+
tag = ossl_asn1_default_tag(example);
1052+
}
1053+
}
1054+
else {
1055+
tag = ossl_asn1_default_tag(self);
1056+
}
9731057
explicit = ossl_asn1_is_explicit(self);
9741058
value = join_der(ossl_asn1_get_value(self));
9751059

976-
seq_len = ASN1_object_size(1, RSTRING_LEN(value), tag);
977-
length = ASN1_object_size(1, seq_len, tn);
1060+
seq_len = ASN1_object_size(constructed, RSTRING_LEN(value), tag);
1061+
length = ASN1_object_size(constructed, seq_len, tn);
9781062
str = rb_str_new(0, length);
9791063
p = (unsigned char *)RSTRING_PTR(str);
9801064
if(tc == V_ASN1_UNIVERSAL)
981-
ASN1_put_object(&p, 1, RSTRING_LEN(value), tn, tc);
1065+
ASN1_put_object(&p, constructed, RSTRING_LEN(value), tn, tc);
9821066
else{
9831067
if(explicit){
984-
ASN1_put_object(&p, 1, seq_len, tn, tc);
985-
ASN1_put_object(&p, 1, RSTRING_LEN(value), tag, V_ASN1_UNIVERSAL);
1068+
ASN1_put_object(&p, constructed, seq_len, tn, tc);
1069+
ASN1_put_object(&p, constructed, RSTRING_LEN(value), tag, V_ASN1_UNIVERSAL);
9861070
}
987-
else ASN1_put_object(&p, 1, RSTRING_LEN(value), tn, tc);
1071+
else{
1072+
ASN1_put_object(&p, constructed, RSTRING_LEN(value), tn, tc);
1073+
}
9881074
}
9891075
memcpy(p, RSTRING_PTR(value), RSTRING_LEN(value));
9901076
p += RSTRING_LEN(value);
@@ -1080,6 +1166,7 @@ OSSL_ASN1_IMPL_FACTORY_METHOD(UTCTime)
10801166
OSSL_ASN1_IMPL_FACTORY_METHOD(GeneralizedTime)
10811167
OSSL_ASN1_IMPL_FACTORY_METHOD(Sequence)
10821168
OSSL_ASN1_IMPL_FACTORY_METHOD(Set)
1169+
OSSL_ASN1_IMPL_FACTORY_METHOD(EndOfContent)
10831170

10841171
void
10851172
Init_ossl_asn1()
@@ -1115,11 +1202,13 @@ Init_ossl_asn1()
11151202
rb_attr(cASN1Data, rb_intern("value"), 1, 1, 0);
11161203
rb_attr(cASN1Data, rb_intern("tag"), 1, 1, 0);
11171204
rb_attr(cASN1Data, rb_intern("tag_class"), 1, 1, 0);
1205+
rb_attr(cASN1Data, rb_intern("infinite_length"), 1, 1, 0);
11181206
rb_define_method(cASN1Data, "initialize", ossl_asn1data_initialize, 3);
11191207
rb_define_method(cASN1Data, "to_der", ossl_asn1data_to_der, 0);
11201208

11211209
cASN1Primitive = rb_define_class_under(mASN1, "Primitive", cASN1Data);
11221210
rb_attr(cASN1Primitive, rb_intern("tagging"), 1, 1, Qtrue);
1211+
rb_undef_method(cASN1Primitive, "infinite_length=");
11231212
rb_define_method(cASN1Primitive, "initialize", ossl_asn1_initialize, -1);
11241213
rb_define_method(cASN1Primitive, "to_der", ossl_asn1prim_to_der, 0);
11251214

@@ -1160,11 +1249,15 @@ do{\
11601249
OSSL_ASN1_DEFINE_CLASS(Sequence, Constructive);
11611250
OSSL_ASN1_DEFINE_CLASS(Set, Constructive);
11621251

1252+
OSSL_ASN1_DEFINE_CLASS(EndOfContent, Data);
1253+
11631254
rb_define_singleton_method(cASN1ObjectId, "register", ossl_asn1obj_s_register, 3);
11641255
rb_define_method(cASN1ObjectId, "sn", ossl_asn1obj_get_sn, 0);
11651256
rb_define_method(cASN1ObjectId, "ln", ossl_asn1obj_get_ln, 0);
11661257
rb_define_method(cASN1ObjectId, "oid", ossl_asn1obj_get_oid, 0);
11671258
rb_define_alias(cASN1ObjectId, "short_name", "sn");
11681259
rb_define_alias(cASN1ObjectId, "long_name", "ln");
11691260
rb_attr(cASN1BitString, rb_intern("unused_bits"), 1, 1, 0);
1261+
1262+
rb_define_method(cASN1EndOfContent, "initialize", ossl_asn1eoc_initialize, 0);
11701263
}

0 commit comments

Comments
 (0)