Fix error-handling for i2a_ASN1_OBJECT.

Some BIO_write failures weren't handled. Otherwise would successfully
write truncated results. The other i2a functions all report -1 on
truncation, so match. While I'm here, write a test to make sure I didn't
break this.

Change-Id: If17d0209e75c15b3f37bceb1cdfb480fd2c62c4d
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/49931
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
grpc-202302
David Benjamin 3 years ago committed by Boringssl LUCI CQ
parent ae274a25a2
commit 686d05aaa5
  1. 41
      crypto/asn1/a_object.c
  2. 82
      crypto/asn1/asn1_test.cc

@ -110,26 +110,37 @@ int i2t_ASN1_OBJECT(char *buf, int buf_len, const ASN1_OBJECT *a)
return OBJ_obj2txt(buf, buf_len, a, 0);
}
static int write_str(BIO *bp, const char *str)
{
int len = strlen(str);
return BIO_write(bp, str, len) == len ? len : -1;
}
int i2a_ASN1_OBJECT(BIO *bp, const ASN1_OBJECT *a)
{
char buf[80], *p = buf;
int i;
if (a == NULL || a->data == NULL) {
return write_str(bp, "NULL");
}
if ((a == NULL) || (a->data == NULL))
return (BIO_write(bp, "NULL", 4));
i = i2t_ASN1_OBJECT(buf, sizeof buf, a);
if (i > (int)(sizeof(buf) - 1)) {
p = OPENSSL_malloc(i + 1);
if (!p)
char buf[80], *allocated = NULL;
const char *str = buf;
int len = i2t_ASN1_OBJECT(buf, sizeof(buf), a);
if (len > (int)sizeof(buf) - 1) {
/* The input was truncated. Allocate a buffer that fits. */
allocated = OPENSSL_malloc(len + 1);
if (allocated == NULL) {
return -1;
i2t_ASN1_OBJECT(p, i + 1, a);
}
len = i2t_ASN1_OBJECT(allocated, len + 1, a);
str = allocated;
}
if (len <= 0) {
str = "<INVALID>";
}
if (i <= 0)
return BIO_write(bp, "<INVALID>", 9);
BIO_write(bp, p, i);
if (p != buf)
OPENSSL_free(p);
return (i);
int ret = write_str(bp, str);
OPENSSL_free(allocated);
return ret;
}
ASN1_OBJECT *d2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp,

@ -1587,6 +1587,88 @@ TEST(ASN1Test, StringCmp) {
}
}
TEST(ASN1Test, PrintASN1Object) {
const struct {
std::vector<uint8_t> in;
const char *expected;
} kDataTests[] = {
// Known OIDs print as the name.
{{0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01}, "rsaEncryption"},
// Unknown OIDs print in decimal.
{{0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x04, 0x01, 0x84, 0xb7, 0x09, 0x00},
"1.2.840.113554.4.1.72585.0"},
// Inputs which cannot be parsed as OIDs print as "<INVALID>".
{{0xff}, "<INVALID>"},
// The function has an internal 80-byte buffer. Test inputs at that
// boundary. First, 78 characters.
{{0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x04, 0x01, 0x84, 0xb7,
0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
"1.2.840.113554.4.1.72585.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0."
"0.0.0.1"},
// 79 characters.
{{0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x04, 0x01, 0x84, 0xb7,
0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a},
"1.2.840.113554.4.1.72585.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0."
"0.0.0.10"},
// 80 characters.
{{0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x04, 0x01, 0x84, 0xb7,
0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64},
"1.2.840.113554.4.1.72585.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0."
"0.0.0.100"},
// 81 characters.
{{0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x04, 0x01, 0x84, 0xb7,
0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87, 0x68},
"1.2.840.113554.4.1.72585.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0."
"0.0.0.1000"},
// 82 characters.
{{0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x04, 0x01, 0x84, 0xb7,
0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xce, 0x10},
"1.2.840.113554.4.1.72585.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0."
"0.0.0.10000"},
};
for (const auto &t : kDataTests) {
SCOPED_TRACE(Bytes(t.in));
bssl::UniquePtr<ASN1_OBJECT> obj(ASN1_OBJECT_create(
NID_undef, t.in.data(), t.in.size(), /*sn=*/nullptr, /*ln=*/nullptr));
ASSERT_TRUE(obj);
bssl::UniquePtr<BIO> bio(BIO_new(BIO_s_mem()));
ASSERT_TRUE(bio);
int len = i2a_ASN1_OBJECT(bio.get(), obj.get());
EXPECT_EQ(len, static_cast<int>(strlen(t.expected)));
const uint8_t *bio_data;
size_t bio_len;
BIO_mem_contents(bio.get(), &bio_data, &bio_len);
EXPECT_EQ(t.expected,
std::string(reinterpret_cast<const char *>(bio_data), bio_len));
}
// Test writing NULL.
bssl::UniquePtr<BIO> bio(BIO_new(BIO_s_mem()));
ASSERT_TRUE(bio);
int len = i2a_ASN1_OBJECT(bio.get(), nullptr);
EXPECT_EQ(len, 4);
const uint8_t *bio_data;
size_t bio_len;
BIO_mem_contents(bio.get(), &bio_data, &bio_len);
EXPECT_EQ("NULL",
std::string(reinterpret_cast<const char *>(bio_data), bio_len));
}
// The ASN.1 macros do not work on Windows shared library builds, where usage of
// |OPENSSL_EXPORT| is a bit stricter.
#if !defined(OPENSSL_WINDOWS) || !defined(BORINGSSL_SHARED_LIBRARY)

Loading…
Cancel
Save