diff --git a/ext/openssl/ossl_asn1.c b/ext/openssl/ossl_asn1.c index 87342d68b..efa6b7874 100644 --- a/ext/openssl/ossl_asn1.c +++ b/ext/openssl/ossl_asn1.c @@ -682,8 +682,10 @@ to_der_internal(VALUE self, int constructed, int indef_len, VALUE body) ASN1_put_object(&p, encoding, body_length, default_tag_number, V_ASN1_UNIVERSAL); memcpy(p, RSTRING_PTR(body), body_length); p += body_length; - if (indef_len) + if (indef_len) { + ASN1_put_eoc(&p); /* For inner object */ ASN1_put_eoc(&p); /* For wrapper object */ + } } else { total_length = ASN1_object_size(encoding, body_length, tag_number); @@ -692,8 +694,10 @@ to_der_internal(VALUE self, int constructed, int indef_len, VALUE body) ASN1_put_object(&p, encoding, body_length, tag_number, tag_class); memcpy(p, RSTRING_PTR(body), body_length); p += body_length; + if (indef_len) + ASN1_put_eoc(&p); } - ossl_str_adjust(str, p); + assert(p - (unsigned char *)RSTRING_PTR(str) == total_length); return str; } @@ -815,13 +819,13 @@ int_ossl_asn1_decode0_cons(unsigned char **pp, long max_len, long length, value = ossl_asn1_decode0(pp, available_len, &off, depth + 1, yield, &inner_read); *num_read += inner_read; available_len -= inner_read; - rb_ary_push(ary, value); if (indefinite && ossl_asn1_tag(value) == V_ASN1_EOC && ossl_asn1_get_tag_class(value) == sym_UNIVERSAL) { break; } + rb_ary_push(ary, value); } if (tc == sym_UNIVERSAL) { @@ -1180,6 +1184,12 @@ ossl_asn1cons_to_der(VALUE self) if (indef_len && rb_obj_is_kind_of(item, cASN1EndOfContent)) { if (i != RARRAY_LEN(ary) - 1) ossl_raise(eASN1Error, "illegal EOC octets in value"); + + /* + * EOC is not really part of the content, but we required to add one + * at the end in the past. + */ + break; } item = ossl_to_der_if_possible(item); diff --git a/test/test_asn1.rb b/test/test_asn1.rb index d3945d36d..9ac6b9be3 100644 --- a/test/test_asn1.rb +++ b/test/test_asn1.rb @@ -339,10 +339,8 @@ def test_sequence OpenSSL::ASN1::Sequence.new([]), OpenSSL::ASN1::OctetString.new(B(%w{ 00 })) ]) - expected = OpenSSL::ASN1::Sequence.new([ - OpenSSL::ASN1::OctetString.new(B(%w{ 00 })), - OpenSSL::ASN1::EndOfContent.new - ]) + + expected = OpenSSL::ASN1::Sequence.new([OpenSSL::ASN1::OctetString.new(B(%w{ 00 }))]) expected.indefinite_length = true encode_decode_test B(%w{ 30 80 04 01 00 00 00 }), expected @@ -354,6 +352,14 @@ def test_sequence ]) obj.indefinite_length = true assert_raise(OpenSSL::ASN1::ASN1Error) { obj.to_der } + + # The last EOC in value is ignored if indefinite length form is used + expected = OpenSSL::ASN1::Sequence.new([ + OpenSSL::ASN1::OctetString.new(B(%w{ 00 })), + OpenSSL::ASN1::EndOfContent.new + ]) + expected.indefinite_length = true + encode_test B(%w{ 30 80 04 01 00 00 00 }), expected end def test_set @@ -363,10 +369,7 @@ def test_set OpenSSL::ASN1::Sequence.new([]), OpenSSL::ASN1::OctetString.new(B(%w{ 00 })) ]) - expected = OpenSSL::ASN1::Set.new([ - OpenSSL::ASN1::OctetString.new(B(%w{ 00 })), - OpenSSL::ASN1::EndOfContent.new - ]) + expected = OpenSSL::ASN1::Set.new([OpenSSL::ASN1::OctetString.new(B(%w{ 00 }))]) expected.indefinite_length = true encode_decode_test B(%w{ 31 80 04 01 00 00 00 }), expected end @@ -431,12 +434,15 @@ def test_basic_asn1data encode_decode_test B(%w{ 41 81 80 } + %w{ AB CD } * 64), OpenSSL::ASN1::ASN1Data.new(B(%w{ AB CD } * 64), 1, :APPLICATION) encode_decode_test B(%w{ 41 82 01 00 } + %w{ AB CD } * 128), OpenSSL::ASN1::ASN1Data.new(B(%w{ AB CD } * 128), 1, :APPLICATION) encode_decode_test B(%w{ 61 00 }), OpenSSL::ASN1::ASN1Data.new([], 1, :APPLICATION) + obj = OpenSSL::ASN1::ASN1Data.new([OpenSSL::ASN1::ASN1Data.new(B(%w{ AB CD }), 2, :PRIVATE)], 1, :APPLICATION) + obj.indefinite_length = true + encode_decode_test B(%w{ 61 80 C2 02 AB CD 00 00 }), obj obj = OpenSSL::ASN1::ASN1Data.new([ OpenSSL::ASN1::ASN1Data.new(B(%w{ AB CD }), 2, :PRIVATE), OpenSSL::ASN1::EndOfContent.new ], 1, :APPLICATION) obj.indefinite_length = true - encode_decode_test B(%w{ 61 80 C2 02 AB CD 00 00 }), obj + encode_test B(%w{ 61 80 C2 02 AB CD 00 00 }), obj obj = OpenSSL::ASN1::ASN1Data.new(B(%w{ AB CD }), 1, :UNIVERSAL) obj.indefinite_length = true assert_raise(OpenSSL::ASN1::ASN1Error) { obj.to_der } @@ -460,12 +466,12 @@ def test_basic_constructed encode_test B(%w{ 21 00 }), OpenSSL::ASN1::Constructive.new([], 1, nil, :UNIVERSAL) encode_test B(%w{ A1 00 }), OpenSSL::ASN1::Constructive.new([], 1, nil, :CONTEXT_SPECIFIC) encode_test B(%w{ 21 04 04 02 AB CD }), OpenSSL::ASN1::Constructive.new([octet_string], 1) - obj = OpenSSL::ASN1::Constructive.new([ - octet_string, - OpenSSL::ASN1::EndOfContent.new - ], 1) + obj = OpenSSL::ASN1::Constructive.new([octet_string], 1) obj.indefinite_length = true encode_decode_test B(%w{ 21 80 04 02 AB CD 00 00 }), obj + obj = OpenSSL::ASN1::Constructive.new([octet_string, OpenSSL::ASN1::EndOfContent.new], 1) + obj.indefinite_length = true + encode_test B(%w{ 21 80 04 02 AB CD 00 00 }), obj end def test_prim_explicit_tagging @@ -570,32 +576,26 @@ def test_recursive_octet_string_parse assert_equal(OpenSSL::ASN1::Constructive, asn1.class) assert_universal(OpenSSL::ASN1::OCTET_STRING, asn1) assert_equal(true, asn1.indefinite_length) - assert_equal(4, asn1.value.size) + assert_equal(3, asn1.value.size) nested1 = asn1.value[0] assert_equal(OpenSSL::ASN1::Constructive, nested1.class) assert_universal(OpenSSL::ASN1::OCTET_STRING, nested1) assert_equal(true, nested1.indefinite_length) - assert_equal(2, nested1.value.size) + assert_equal(1, nested1.value.size) oct1 = nested1.value[0] assert_universal(OpenSSL::ASN1::OCTET_STRING, oct1) assert_equal(false, oct1.indefinite_length) - assert_universal(OpenSSL::ASN1::EOC, nested1.value[1]) - assert_equal(false, nested1.value[1].indefinite_length) nested2 = asn1.value[1] assert_equal(OpenSSL::ASN1::Constructive, nested2.class) assert_universal(OpenSSL::ASN1::OCTET_STRING, nested2) assert_equal(true, nested2.indefinite_length) - assert_equal(2, nested2.value.size) + assert_equal(1, nested2.value.size) oct2 = nested2.value[0] assert_universal(OpenSSL::ASN1::OCTET_STRING, oct2) assert_equal(false, oct2.indefinite_length) - assert_universal(OpenSSL::ASN1::EOC, nested2.value[1]) - assert_equal(false, nested2.value[1].indefinite_length) oct3 = asn1.value[2] assert_universal(OpenSSL::ASN1::OCTET_STRING, oct3) assert_equal(false, oct3.indefinite_length) - assert_universal(OpenSSL::ASN1::EOC, asn1.value[3]) - assert_equal(false, asn1.value[3].indefinite_length) end def test_decode_constructed_overread