@@ -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
169173VALUE mASN1 ;
170174VALUE eASN1Error ;
@@ -173,6 +177,7 @@ VALUE cASN1Data;
173177VALUE cASN1Primitive ;
174178VALUE cASN1Constructive ;
175179
180+ VALUE cASN1EndOfContent ;
176181VALUE cASN1Boolean ; /* BOOLEAN */
177182VALUE cASN1Integer , cASN1Enumerated ; /* INTEGER */
178183VALUE cASN1BitString ; /* BIT STRING */
@@ -449,7 +454,7 @@ typedef struct {
449454} ossl_asn1_info_t ;
450455
451456static 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)
684690static VALUE
685691ossl_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+
901952static int
902953ossl_i2d_ASN1_TYPE (ASN1_TYPE * a , unsigned char * * pp )
903954{
@@ -962,29 +1013,64 @@ ossl_asn1prim_to_der(VALUE self)
9621013static VALUE
9631014ossl_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)
10801166OSSL_ASN1_IMPL_FACTORY_METHOD (GeneralizedTime )
10811167OSSL_ASN1_IMPL_FACTORY_METHOD (Sequence )
10821168OSSL_ASN1_IMPL_FACTORY_METHOD (Set )
1169+ OSSL_ASN1_IMPL_FACTORY_METHOD (EndOfContent )
10831170
10841171void
10851172Init_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