1212#include < botan/internal/asn1_utils.h>
1313#include < botan/internal/int_utils.h>
1414#include < botan/internal/loadstor.h>
15+ #include < algorithm>
1516#include < memory>
1617
1718namespace Botan {
@@ -37,6 +38,12 @@ size_t decode_tag(DataSource* ber, ASN1_Type& type_tag, ASN1_Class& class_tag) {
3738 if ((*b & 0x1F ) != 0x1F ) {
3839 type_tag = ASN1_Type (*b & 0x1F );
3940 class_tag = ASN1_Class (*b & 0xE0 );
41+ // The EOC marker is primitive; a constructed universal tag 0 has no
42+ // valid meaning and would otherwise bypass the EOC handling, which
43+ // matches on (Eoc, Universal) exactly
44+ if (type_tag == ASN1_Type::Eoc && class_tag == ASN1_Class::Constructed) {
45+ throw BER_Decoding_Error (" EOC tag with constructed encoding" );
46+ }
4047 return 1 ;
4148 }
4249
@@ -49,7 +56,8 @@ size_t decode_tag(DataSource* ber, ASN1_Type& type_tag, ASN1_Class& class_tag) {
4956 if (!b) {
5057 throw BER_Decoding_Error (" Long-form tag truncated" );
5158 }
52- if ((tag_buf >> 24 ) != 0 ) {
59+ // Reject if shifting in another 7 bits would overflow the uint32_t tag
60+ if ((tag_buf >> 25 ) != 0 ) {
5361 throw BER_Decoding_Error (" Long-form tag overflowed 32 bits" );
5462 }
5563 // This is required even by BER (see X.690 section 8.1.2.4.2 sentence c).
@@ -197,6 +205,12 @@ size_t peek_tag(DataSource* src, size_t offset, ASN1_Type& type_tag, ASN1_Class&
197205 if ((b & 0x1F ) != 0x1F ) {
198206 type_tag = ASN1_Type (b & 0x1F );
199207 class_tag = ASN1_Class (b & 0xE0 );
208+ // The EOC marker is primitive; a constructed universal tag 0 has no
209+ // valid meaning and would otherwise bypass the EOC handling, which
210+ // matches on (Eoc, Universal) exactly
211+ if (type_tag == ASN1_Type::Eoc && class_tag == ASN1_Class::Constructed) {
212+ throw BER_Decoding_Error (" EOC tag with constructed encoding" );
213+ }
200214 return 1 ;
201215 }
202216
@@ -208,7 +222,8 @@ size_t peek_tag(DataSource* src, size_t offset, ASN1_Type& type_tag, ASN1_Class&
208222 if (src->peek (&b, 1 , offset + tag_bytes) == 0 ) {
209223 throw BER_Decoding_Error (" Long-form tag truncated" );
210224 }
211- if ((tag_buf >> 24 ) != 0 ) {
225+ // Reject if shifting in another 7 bits would overflow the uint32_t tag
226+ if ((tag_buf >> 25 ) != 0 ) {
212227 throw BER_Decoding_Error (" Long-form tag overflowed 32 bits" );
213228 }
214229 // Required even by BER (X.690 section 8.1.2.4.2 sentence c).
@@ -246,7 +261,8 @@ size_t peek_tag(DataSource* src, size_t offset, ASN1_Type& type_tag, ASN1_Class&
246261* Returns the decoded length and sets field_size to the number of bytes consumed.
247262* For indefinite-length encoding, recursively scans ahead to find the EOC marker.
248263*/
249- size_t peek_length (DataSource* src, size_t offset, size_t & field_size, size_t allow_indef, bool constructed) {
264+ size_t peek_length (
265+ DataSource* src, size_t offset, size_t & field_size, size_t allow_indef, bool constructed, bool der_mode) {
250266 uint8_t b = 0 ;
251267 if (src->peek (&b, 1 , offset) == 0 ) {
252268 throw BER_Decoding_Error (" Length field not found" );
@@ -264,6 +280,10 @@ size_t peek_length(DataSource* src, size_t offset, size_t& field_size, size_t al
264280 }
265281
266282 if (num_length_bytes == 0 ) {
283+ // Indefinite length is not allowed in DER
284+ if (der_mode) {
285+ throw BER_Decoding_Error (" Detected indefinite-length encoding in DER structure" );
286+ }
267287 // Indefinite length is only valid for constructed types (X.690 8.1.3.2)
268288 if (!constructed) {
269289 throw BER_Decoding_Error (" Indefinite-length encoding used with non-constructed type" );
@@ -303,7 +323,8 @@ size_t find_eoc(DataSource* src, size_t base_offset, size_t allow_indef) {
303323 }
304324
305325 size_t length_size = 0 ;
306- const size_t item_size = peek_length (src, offset + tag_size, length_size, allow_indef, is_constructed (class_tag));
326+ const size_t item_size =
327+ peek_length (src, offset + tag_size, length_size, allow_indef, is_constructed (class_tag), false );
307328
308329 if (auto new_offset = checked_add (offset, tag_size, length_size, item_size)) {
309330 offset = new_offset.value ();
@@ -397,6 +418,39 @@ class DataSource_Span final : public DataSource {
397418 size_t m_offset = 0 ;
398419};
399420
421+ /*
422+ * Verify that the elements of a SET appear in sorted order, comparing the full
423+ * encoding of each element as an octet string. DER requires this canonical
424+ * ordering. Throws if the elements are not sorted.
425+ */
426+ void verify_set_is_sorted (std::span<const uint8_t > content) {
427+ DataSource_Span src (content);
428+ size_t offset = 0 ;
429+ std::optional<std::span<const uint8_t >> prev;
430+
431+ while (offset < content.size ()) {
432+ ASN1_Type type_tag = ASN1_Type::NoObject;
433+ ASN1_Class class_tag = ASN1_Class::NoObject;
434+ const size_t tag_size = peek_tag (&src, offset, type_tag, class_tag);
435+
436+ size_t length_size = 0 ;
437+ const size_t item_size =
438+ peek_length (&src, offset + tag_size, length_size, /* allow_indef=*/ 0 , is_constructed (class_tag), true );
439+
440+ const auto end = checked_add (offset, tag_size, length_size, item_size);
441+ if (!end || *end > content.size ()) {
442+ throw BER_Decoding_Error (" SET element exceeds available data" );
443+ }
444+
445+ const auto elem = content.subspan (offset, *end - offset);
446+ if (prev && std::lexicographical_compare (elem.begin (), elem.end (), prev->begin (), prev->end ())) {
447+ throw BER_Decoding_Error (" Detected unsorted SET in DER structure" );
448+ }
449+ prev = elem;
450+ offset = *end;
451+ }
452+ }
453+
400454} // namespace
401455
402456BER_Decoder::~BER_Decoder () = default ;
@@ -488,6 +542,10 @@ BER_Object BER_Decoder::get_next_object() {
488542 throw BER_Decoding_Error (" EOC marker with non-zero length" );
489543 }
490544
545+ if (const auto max_size = m_limits.max_object_size (); max_size && dl.content_length () > *max_size) {
546+ throw BER_Decoding_Error (" Encoded object exceeds maximum size" );
547+ }
548+
491549 if (!m_source->check_available (dl.total_length ())) {
492550 throw BER_Decoding_Error (" Value truncated" );
493551 }
@@ -509,10 +567,16 @@ BER_Object BER_Decoder::get_next_object() {
509567 if (m_limits.require_der_encoding ()) {
510568 throw BER_Decoding_Error (" Detected EOC marker in DER structure" );
511569 }
512- continue ;
513- } else {
514- break ;
570+ // An EOC marker is only valid as an indefinite-length terminator, which
571+ // is consumed above when reading the indefinite-length object. A
572+ // standalone EOC is rejected unless the caller opted to tolerate it.
573+ if (m_limits.allow_standalone_eoc ()) {
574+ continue ;
575+ }
576+ throw BER_Decoding_Error (" Encountered EOC marker outside of indefinite-length encoding" );
515577 }
578+
579+ break ;
516580 }
517581
518582 return next;
@@ -550,6 +614,12 @@ void BER_Decoder::push_back(BER_Object&& obj) {
550614BER_Decoder BER_Decoder::start_cons (ASN1_Type type_tag, ASN1_Class class_tag) {
551615 BER_Object obj = get_next_object ();
552616 obj.assert_is_a (type_tag, class_tag | ASN1_Class::Constructed);
617+
618+ // In DER mode the elements of a universal SET must appear in sorted order
619+ if (m_limits.require_der_encoding () && type_tag == ASN1_Type::Set && class_tag == ASN1_Class::Universal) {
620+ verify_set_is_sorted (std::span<const uint8_t >{obj.bits (), obj.length ()});
621+ }
622+
553623 BER_Decoder child (std::move (obj), this );
554624 return child;
555625}
@@ -573,6 +643,11 @@ BER_Decoder::BER_Decoder(BER_Object&& obj, BER_Decoder* parent) :
573643 m_source = m_data_src.get ();
574644}
575645
646+ BER_Decoder::BER_Decoder (BER_Object&& obj, Limits limits) : m_limits(limits) {
647+ m_data_src = std::make_unique<DataSource_BERObject>(std::move (obj));
648+ m_source = m_data_src.get ();
649+ }
650+
576651/*
577652* BER_Decoder Constructor
578653*/
@@ -697,11 +772,13 @@ BER_Decoder& BER_Decoder::decode(BigInt& out, ASN1_Type type_tag, ASN1_Class cla
697772 const BER_Object obj = get_next_object ();
698773 obj.assert_is_a (type_tag, class_tag);
699774
775+ // An INTEGER must have at least one content octet (X.690 section 8.3.1)
776+ if (obj.length () == 0 ) {
777+ throw BER_Decoding_Error (" INTEGER encoding has no content octets" );
778+ }
779+
700780 // DER requires minimal INTEGER encoding (X.690 section 8.3.2)
701781 if (m_limits.require_der_encoding ()) {
702- if (obj.length () == 0 ) {
703- throw BER_Decoding_Error (" Detected empty INTEGER encoding in DER structure" );
704- }
705782 if (obj.length () > 1 ) {
706783 if (obj.bits ()[0 ] == 0x00 && (obj.bits ()[1 ] & 0x80 ) == 0 ) {
707784 throw BER_Decoding_Error (" Detected non-minimal INTEGER encoding in DER structure" );
@@ -712,29 +789,25 @@ BER_Decoder& BER_Decoder::decode(BigInt& out, ASN1_Type type_tag, ASN1_Class cla
712789 }
713790 }
714791
715- if (obj.length () == 0 ) {
716- out.clear ();
717- } else {
718- const uint8_t first = obj.bits ()[0 ];
719- const bool negative = (first & 0x80 ) == 0x80 ;
720-
721- if (negative) {
722- secure_vector<uint8_t > vec (obj.bits (), obj.bits () + obj.length ());
723- for (size_t i = obj.length (); i > 0 ; --i) {
724- const bool gt0 = (vec[i - 1 ] > 0 );
725- vec[i - 1 ] -= 1 ;
726- if (gt0) {
727- break ;
728- }
729- }
730- for (size_t i = 0 ; i != obj.length (); ++i) {
731- vec[i] = ~vec[i];
792+ const uint8_t first = obj.bits ()[0 ];
793+ const bool negative = (first & 0x80 ) == 0x80 ;
794+
795+ if (negative) {
796+ secure_vector<uint8_t > vec (obj.bits (), obj.bits () + obj.length ());
797+ for (size_t i = obj.length (); i > 0 ; --i) {
798+ const bool gt0 = (vec[i - 1 ] > 0 );
799+ vec[i - 1 ] -= 1 ;
800+ if (gt0) {
801+ break ;
732802 }
733- out._assign_from_bytes (vec);
734- out.flip_sign ();
735- } else {
736- out._assign_from_bytes (obj.data ());
737803 }
804+ for (size_t i = 0 ; i != obj.length (); ++i) {
805+ vec[i] = ~vec[i];
806+ }
807+ out._assign_from_bytes (vec);
808+ out.flip_sign ();
809+ } else {
810+ out._assign_from_bytes (obj.data ());
738811 }
739812
740813 return (*this );
@@ -755,9 +828,10 @@ void asn1_decode_binary_string(std::vector<uint8_t, Alloc>& buffer,
755828 bool require_der) {
756829 obj.assert_is_a (type_tag, class_tag);
757830
758- // DER requires BIT STRING and OCTET STRING to use primitive encoding
759- if (require_der && is_constructed (obj)) {
760- throw BER_Decoding_Error (" Detected constructed string encoding in DER structure" );
831+ // Only primitive OCTET STRING/BIT STRING are supported; constructed
832+ // (fragmented) BER forms are rejected rather than concatenated.
833+ if (is_constructed (obj)) {
834+ throw BER_Decoding_Error (" Constructed OCTET STRING/BIT STRING is not supported" );
761835 }
762836
763837 if (real_type == ASN1_Type::OctetString) {
@@ -797,8 +871,10 @@ void asn1_decode_binary_string(std::vector<uint8_t, Alloc>& buffer,
797871uint8_t asn1_bitstring_unused_bits (const BER_Object& obj, ASN1_Type type_tag, ASN1_Class class_tag, bool require_der) {
798872 obj.assert_is_a (type_tag, class_tag);
799873
800- if (require_der && is_constructed (obj)) {
801- throw BER_Decoding_Error (" Detected constructed string encoding in DER structure" );
874+ // Only primitive BIT STRING is supported; constructed (fragmented) BER
875+ // forms are rejected rather than concatenated.
876+ if (is_constructed (obj)) {
877+ throw BER_Decoding_Error (" Constructed OCTET STRING/BIT STRING is not supported" );
802878 }
803879
804880 if (obj.length () == 0 ) {
0 commit comments