Skip to content

Conversation

@botovq
Copy link
Owner

@botovq botovq commented Jan 22, 2026

This removes the implicit truncation dance from i2c_ASN1_BIT_STRING(), still respecting ASN1_STRING_FLAG_BITS_LEFT and only using the bits from a->flags if that is set. Clean up and reorder the implementation.

This changes the encoding of bit strings set via ASN1_BIT_STRING_set() and ASN1_STRING_set() unless that flag is set by the application. The ASN1_BIT_STRING_set() is only used without ASN1_STRING_FLAG_BITS_LEFT by the yubico-piv-tool, where this results in erroneous behavior due to incorrect porting of the code to OpenSSL 1.1.

It adds (perhaps somewhat too clever) code to ensure the truncation behavior of ASN1_BIT_STRING_set_bit() is unmodified. It now sets ASN1_STRING_FLAG_BITS_LEFT and so that the resulting DER encoding remains the same, which is needed for things relying on that such as the code setting the keyUsage bits. This is required for correct DER encoding, because:

X.680, 22.7:

When a "NamedBitList" is used in defining a bitstring type ASN.1
encoding rules are free to add (or remove) arbitrarily any trailing 0
bits to (or from) values that are being encoded or decoded. Application
designers should therefore ensure that different semantics are not
associated with such vlaues which differ only in the number of trailing
0 bits.

X.690, 11.2.2:

Where ITU-T Rec. X.680 | ISO/IEC 8824-1, 22.7, applies, the bitstring
shall have all trailing 0 bits removed before it is encoded.

Note 1 - In the case where a size constraint has been applied, the
abstract value delivered by a decoder to the application will be one of
those satisfying the size constraint and differing from the transmitted
value only in the number of trailing zero bits.

Note 2 - If a bitstring value has no 1 bits, then an encoder shall
encode the value with a length of 1 and an initial octet set to 0.

See openssl/openssl#29711

This removes the implicit truncation dance from i2c_ASN1_BIT_STRING(),
still respecting ASN1_STRING_FLAG_BITS_LEFT and only using the bits
from a->flags if that is set. Clean up and reorder the implementation.

This changes the encoding of bit strings set via ASN1_BIT_STRING_set()
and ASN1_STRING_set() unless that flag is set by the application. The
ASN1_BIT_STRING_set() is only used without ASN1_STRING_FLAG_BITS_LEFT
by the yubico-piv-tool, where this results in erroneous behavior due
to incorrect porting of the code to OpenSSL 1.1.

It adds (perhaps somewhat too clever) code to ensure the truncation
behavior of ASN1_BIT_STRING_set_bit() is unmodified. It now sets
ASN1_STRING_FLAG_BITS_LEFT and so that the resulting DER encoding
remains the same, which is needed for things relying on that such as
the code setting the keyUsage bits. This is required for correct DER
encoding, because:

X.680, 22.7:

 When a "NamedBitList" is used in defining a bitstring type ASN.1
 encoding rules are free to add (or remove) arbitrarily any trailing 0
 bits to (or from) values that are being encoded or decoded. Application
 designers should therefore ensure that different semantics are not
 associated with such vlaues which differ only in the number of trailing
 0 bits.

X.690, 11.2.2:

 Where ITU-T Rec. X.680 | ISO/IEC 8824-1, 22.7, applies, the bitstring
 shall have all trailing 0 bits removed before it is encoded.

 Note 1 - In the case where a size constraint has been applied, the
 abstract value delivered by a decoder to the application will be one of
 those satisfying the size constraint and differing from the transmitted
 value only in the number of trailing zero bits.

 Note 2 - If a bitstring value has no 1 bits, then an encoder shall
 encode the value with a length of 1 and an initial octet set to 0.

See openssl/openssl#29711
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant