Check tag class and constructed bit in d2i_ASN1_BOOLEAN. d2i_ASN1_BOOLEAN and i2d_ASN1_BOOLEAN don't go through the macros because ASN1_BOOLEAN is a slightly weird type (int instead of pointer). Their tag checks were missing a few bits. This does not affect any other d2i functions. Those already go through the ASN1_ITEM machinery. Change-Id: Ic892cd2a8b8f9ceb11e43d931f8aa6df921997d3 Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/49866 Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/asn1/a_bool.c b/crypto/asn1/a_bool.c index 1282176..3f32e80 100644 --- a/crypto/asn1/a_bool.c +++ b/crypto/asn1/a_bool.c
@@ -99,11 +99,16 @@ return -1; } - if (tag != V_ASN1_BOOLEAN) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_EXPECTING_A_BOOLEAN); + if (inf & V_ASN1_CONSTRUCTED) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_TYPE_NOT_PRIMITIVE); return -1; } + if (tag != V_ASN1_BOOLEAN || xclass != V_ASN1_UNIVERSAL) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_EXPECTING_A_BOOLEAN); + return -1; + } + if (len != 1) { OPENSSL_PUT_ERROR(ASN1, ASN1_R_BOOLEAN_IS_WRONG_LENGTH); return -1;
diff --git a/crypto/asn1/asn1_test.cc b/crypto/asn1/asn1_test.cc index 738e422..1ea7644 100644 --- a/crypto/asn1/asn1_test.cc +++ b/crypto/asn1/asn1_test.cc
@@ -132,15 +132,49 @@ TestSerialize(obj, i2d_ASN1_OBJECT, kDER); } -TEST(ASN1Test, SerializeBoolean) { +TEST(ASN1Test, Boolean) { static const uint8_t kTrue[] = {0x01, 0x01, 0xff}; TestSerialize(0xff, i2d_ASN1_BOOLEAN, kTrue); // Other constants are also correctly encoded as TRUE. TestSerialize(1, i2d_ASN1_BOOLEAN, kTrue); TestSerialize(0x100, i2d_ASN1_BOOLEAN, kTrue); + const uint8_t *ptr = kTrue; + EXPECT_EQ(0xff, d2i_ASN1_BOOLEAN(nullptr, &ptr, sizeof(kTrue))); + EXPECT_EQ(ptr, kTrue + sizeof(kTrue)); + static const uint8_t kFalse[] = {0x01, 0x01, 0x00}; TestSerialize(0x00, i2d_ASN1_BOOLEAN, kFalse); + + ptr = kFalse; + EXPECT_EQ(0, d2i_ASN1_BOOLEAN(nullptr, &ptr, sizeof(kFalse))); + EXPECT_EQ(ptr, kFalse + sizeof(kFalse)); + + const std::vector<uint8_t> kInvalidBooleans[] = { + // No tag header. + {}, + // No length. + {0x01}, + // Truncated contents. + {0x01, 0x01}, + // Contents too short or too long. + {0x01, 0x00}, + {0x01, 0x02, 0x00, 0x00}, + // Wrong tag number. + {0x02, 0x01, 0x00}, + // Wrong tag class. + {0x81, 0x01, 0x00}, + // Element is constructed. + {0x21, 0x01, 0x00}, + // TODO(https://crbug.com/boringssl/354): Reject non-DER encodings of TRUE + // and test this. + }; + for (const auto &invalid : kInvalidBooleans) { + SCOPED_TRACE(Bytes(invalid)); + ptr = invalid.data(); + EXPECT_EQ(-1, d2i_ASN1_BOOLEAN(nullptr, &ptr, invalid.size())); + ERR_clear_error(); + } } // The templates go through a different codepath, so test them separately.