external/boringssl: Sync to 915c121bb5d424e09bf05c3aabf172a44e958e28.
This includes the following changes:
https://boringssl.googlesource.com/boringssl/+log/ea52ec98a56a40879b37493f3d1da1a1679e1fba..915c121bb5d424e09bf05c3aabf172a44e958e28
Test: BoringSSL CTS Presubmits
Change-Id: I3f5eba69372b484e19f4ca250c81f208aa5d3dc5
diff --git a/src/crypto/asn1/a_int.c b/src/crypto/asn1/a_int.c
index 8a4edd6..dd74550 100644
--- a/src/crypto/asn1/a_int.c
+++ b/src/crypto/asn1/a_int.c
@@ -347,40 +347,45 @@
int ASN1_INTEGER_set(ASN1_INTEGER *a, long v)
{
- int j, k;
- unsigned int i;
- unsigned char buf[sizeof(long) + 1];
- long d;
-
- a->type = V_ASN1_INTEGER;
- if (a->length < (int)(sizeof(long) + 1)) {
- if (a->data != NULL)
- OPENSSL_free(a->data);
- if ((a->data =
- (unsigned char *)OPENSSL_malloc(sizeof(long) + 1)) != NULL)
- OPENSSL_memset((char *)a->data, 0, sizeof(long) + 1);
+ if (v >= 0) {
+ return ASN1_INTEGER_set_uint64(a, (uint64_t) v);
}
- if (a->data == NULL) {
+
+ if (!ASN1_INTEGER_set_uint64(a, 0 - (uint64_t) v)) {
+ return 0;
+ }
+
+ a->type = V_ASN1_NEG_INTEGER;
+ return 1;
+}
+
+int ASN1_INTEGER_set_uint64(ASN1_INTEGER *out, uint64_t v)
+{
+ uint8_t *const newdata = OPENSSL_malloc(sizeof(uint64_t));
+ if (newdata == NULL) {
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
- return (0);
- }
- d = v;
- if (d < 0) {
- d = -d;
- a->type = V_ASN1_NEG_INTEGER;
+ return 0;
}
- for (i = 0; i < sizeof(long); i++) {
- if (d == 0)
+ OPENSSL_free(out->data);
+ out->data = newdata;
+ v = CRYPTO_bswap8(v);
+ memcpy(out->data, &v, sizeof(v));
+
+ out->type = V_ASN1_INTEGER;
+
+ size_t leading_zeros;
+ for (leading_zeros = 0; leading_zeros < sizeof(uint64_t) - 1;
+ leading_zeros++) {
+ if (out->data[leading_zeros] != 0) {
break;
- buf[i] = (int)d & 0xff;
- d >>= 8;
+ }
}
- j = 0;
- for (k = i - 1; k >= 0; k--)
- a->data[j++] = buf[k];
- a->length = j;
- return (1);
+
+ out->length = sizeof(uint64_t) - leading_zeros;
+ OPENSSL_memmove(out->data, out->data + leading_zeros, out->length);
+
+ return 1;
}
long ASN1_INTEGER_get(const ASN1_INTEGER *a)
diff --git a/src/crypto/asn1/asn1_test.cc b/src/crypto/asn1/asn1_test.cc
index accf3ba..7c114dd 100644
--- a/src/crypto/asn1/asn1_test.cc
+++ b/src/crypto/asn1/asn1_test.cc
@@ -15,6 +15,7 @@
#include <stdio.h>
#include <gtest/gtest.h>
+#include <limits.h>
#include <openssl/asn1.h>
#include <openssl/err.h>
@@ -60,3 +61,30 @@
EXPECT_EQ(Bytes(&kZero, 1), Bytes(obj->value.asn1_string->data,
obj->value.asn1_string->length));
}
+
+TEST(ASN1Test, IntegerSetting) {
+ bssl::UniquePtr<ASN1_INTEGER> by_bn(M_ASN1_INTEGER_new());
+ bssl::UniquePtr<ASN1_INTEGER> by_long(M_ASN1_INTEGER_new());
+ bssl::UniquePtr<ASN1_INTEGER> by_uint64(M_ASN1_INTEGER_new());
+ bssl::UniquePtr<BIGNUM> bn(BN_new());
+
+ const std::vector<int64_t> kValues = {
+ LONG_MIN, -2, -1, 0, 1, 2, 0xff, 0x100, 0xffff, 0x10000, LONG_MAX,
+ };
+ for (const auto &i : kValues) {
+ SCOPED_TRACE(i);
+
+ ASSERT_EQ(1, ASN1_INTEGER_set(by_long.get(), i));
+ const uint64_t abs = i < 0 ? (0 - (uint64_t) i) : i;
+ ASSERT_TRUE(BN_set_u64(bn.get(), abs));
+ BN_set_negative(bn.get(), i < 0);
+ ASSERT_TRUE(BN_to_ASN1_INTEGER(bn.get(), by_bn.get()));
+
+ EXPECT_EQ(0, ASN1_INTEGER_cmp(by_bn.get(), by_long.get()));
+
+ if (i >= 0) {
+ ASSERT_EQ(1, ASN1_INTEGER_set_uint64(by_uint64.get(), i));
+ EXPECT_EQ(0, ASN1_INTEGER_cmp(by_bn.get(), by_uint64.get()));
+ }
+ }
+}
diff --git a/src/crypto/bytestring/ber.c b/src/crypto/bytestring/ber.c
index 4dc94f6..bb5e17c 100644
--- a/src/crypto/bytestring/ber.c
+++ b/src/crypto/bytestring/ber.c
@@ -29,10 +29,7 @@
// is_string_type returns one if |tag| is a string type and zero otherwise. It
// ignores the constructed bit.
static int is_string_type(unsigned tag) {
- if ((tag & 0xc0) != 0) {
- return 0;
- }
- switch (tag & 0x1f) {
+ switch (tag & ~CBS_ASN1_CONSTRUCTED) {
case CBS_ASN1_BITSTRING:
case CBS_ASN1_OCTETSTRING:
case CBS_ASN1_UTF8STRING:
diff --git a/src/crypto/bytestring/bytestring_test.cc b/src/crypto/bytestring/bytestring_test.cc
index 5a6a5c1..1969e73 100644
--- a/src/crypto/bytestring/bytestring_test.cc
+++ b/src/crypto/bytestring/bytestring_test.cc
@@ -123,27 +123,27 @@
uint64_t value;
CBS_init(&data, kData1, sizeof(kData1));
- EXPECT_FALSE(CBS_peek_asn1_tag(&data, 0x1));
- EXPECT_TRUE(CBS_peek_asn1_tag(&data, 0x30));
+ EXPECT_FALSE(CBS_peek_asn1_tag(&data, CBS_ASN1_BOOLEAN));
+ EXPECT_TRUE(CBS_peek_asn1_tag(&data, CBS_ASN1_SEQUENCE));
- ASSERT_TRUE(CBS_get_asn1(&data, &contents, 0x30));
+ ASSERT_TRUE(CBS_get_asn1(&data, &contents, CBS_ASN1_SEQUENCE));
EXPECT_EQ(Bytes("\x01\x02"), Bytes(CBS_data(&contents), CBS_len(&contents)));
CBS_init(&data, kData2, sizeof(kData2));
// data is truncated
- EXPECT_FALSE(CBS_get_asn1(&data, &contents, 0x30));
+ EXPECT_FALSE(CBS_get_asn1(&data, &contents, CBS_ASN1_SEQUENCE));
CBS_init(&data, kData3, sizeof(kData3));
// zero byte length of length
- EXPECT_FALSE(CBS_get_asn1(&data, &contents, 0x30));
+ EXPECT_FALSE(CBS_get_asn1(&data, &contents, CBS_ASN1_SEQUENCE));
CBS_init(&data, kData4, sizeof(kData4));
// long form mistakenly used.
- EXPECT_FALSE(CBS_get_asn1(&data, &contents, 0x30));
+ EXPECT_FALSE(CBS_get_asn1(&data, &contents, CBS_ASN1_SEQUENCE));
CBS_init(&data, kData5, sizeof(kData5));
// length takes too many bytes.
- EXPECT_FALSE(CBS_get_asn1(&data, &contents, 0x30));
+ EXPECT_FALSE(CBS_get_asn1(&data, &contents, CBS_ASN1_SEQUENCE));
CBS_init(&data, kData1, sizeof(kData1));
// wrong tag.
@@ -151,56 +151,72 @@
CBS_init(&data, NULL, 0);
// peek at empty data.
- EXPECT_FALSE(CBS_peek_asn1_tag(&data, 0x30));
+ EXPECT_FALSE(CBS_peek_asn1_tag(&data, CBS_ASN1_SEQUENCE));
CBS_init(&data, NULL, 0);
// optional elements at empty data.
- ASSERT_TRUE(CBS_get_optional_asn1(&data, &contents, &present, 0xa0));
+ ASSERT_TRUE(CBS_get_optional_asn1(
+ &data, &contents, &present,
+ CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0));
EXPECT_FALSE(present);
- ASSERT_TRUE(
- CBS_get_optional_asn1_octet_string(&data, &contents, &present, 0xa0));
+ ASSERT_TRUE(CBS_get_optional_asn1_octet_string(
+ &data, &contents, &present,
+ CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0));
EXPECT_FALSE(present);
EXPECT_EQ(0u, CBS_len(&contents));
- ASSERT_TRUE(CBS_get_optional_asn1_octet_string(&data, &contents, NULL, 0xa0));
+ ASSERT_TRUE(CBS_get_optional_asn1_octet_string(
+ &data, &contents, NULL,
+ CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0));
EXPECT_EQ(0u, CBS_len(&contents));
- ASSERT_TRUE(CBS_get_optional_asn1_uint64(&data, &value, 0xa0, 42));
+ ASSERT_TRUE(CBS_get_optional_asn1_uint64(
+ &data, &value, CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0, 42));
EXPECT_EQ(42u, value);
CBS_init(&data, kData6, sizeof(kData6));
// optional element.
- ASSERT_TRUE(CBS_get_optional_asn1(&data, &contents, &present, 0xa0));
+ ASSERT_TRUE(CBS_get_optional_asn1(
+ &data, &contents, &present,
+ CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0));
EXPECT_FALSE(present);
- ASSERT_TRUE(CBS_get_optional_asn1(&data, &contents, &present, 0xa1));
+ ASSERT_TRUE(CBS_get_optional_asn1(
+ &data, &contents, &present,
+ CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1));
EXPECT_TRUE(present);
EXPECT_EQ(Bytes("\x04\x01\x01"),
Bytes(CBS_data(&contents), CBS_len(&contents)));
CBS_init(&data, kData6, sizeof(kData6));
// optional octet string.
- ASSERT_TRUE(
- CBS_get_optional_asn1_octet_string(&data, &contents, &present, 0xa0));
+ ASSERT_TRUE(CBS_get_optional_asn1_octet_string(
+ &data, &contents, &present,
+ CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0));
EXPECT_FALSE(present);
EXPECT_EQ(0u, CBS_len(&contents));
- ASSERT_TRUE(
- CBS_get_optional_asn1_octet_string(&data, &contents, &present, 0xa1));
+ ASSERT_TRUE(CBS_get_optional_asn1_octet_string(
+ &data, &contents, &present,
+ CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1));
EXPECT_TRUE(present);
EXPECT_EQ(Bytes("\x01"), Bytes(CBS_data(&contents), CBS_len(&contents)));
CBS_init(&data, kData7, sizeof(kData7));
// invalid optional octet string.
- EXPECT_FALSE(
- CBS_get_optional_asn1_octet_string(&data, &contents, &present, 0xa1));
+ EXPECT_FALSE(CBS_get_optional_asn1_octet_string(
+ &data, &contents, &present,
+ CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1));
CBS_init(&data, kData8, sizeof(kData8));
// optional integer.
- ASSERT_TRUE(CBS_get_optional_asn1_uint64(&data, &value, 0xa0, 42));
+ ASSERT_TRUE(CBS_get_optional_asn1_uint64(
+ &data, &value, CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0, 42));
EXPECT_EQ(42u, value);
- ASSERT_TRUE(CBS_get_optional_asn1_uint64(&data, &value, 0xa1, 42));
+ ASSERT_TRUE(CBS_get_optional_asn1_uint64(
+ &data, &value, CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1, 42));
EXPECT_EQ(1u, value);
CBS_init(&data, kData9, sizeof(kData9));
// invalid optional integer.
- EXPECT_FALSE(CBS_get_optional_asn1_uint64(&data, &value, 0xa1, 42));
+ EXPECT_FALSE(CBS_get_optional_asn1_uint64(
+ &data, &value, CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1, 42));
unsigned tag;
CBS_init(&data, kData1, sizeof(kData1));
@@ -217,6 +233,54 @@
Bytes(CBS_data(&contents), CBS_len(&contents)));
}
+TEST(CBSTest, ParseASN1Tag) {
+ const struct {
+ bool ok;
+ unsigned tag;
+ std::vector<uint8_t> in;
+ } kTests[] = {
+ {true, CBS_ASN1_SEQUENCE, {0x30, 0}},
+ {true, CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 4, {0xa4, 0}},
+ {true, CBS_ASN1_APPLICATION | 30, {0x5e, 0}},
+ {true, CBS_ASN1_APPLICATION | 31, {0x5f, 0x1f, 0}},
+ {true, CBS_ASN1_APPLICATION | 32, {0x5f, 0x20, 0}},
+ {true,
+ CBS_ASN1_PRIVATE | CBS_ASN1_CONSTRUCTED | 0x1fffffff,
+ {0xff, 0x81, 0xff, 0xff, 0xff, 0x7f, 0}},
+ // Tag number fits in unsigned but not |CBS_ASN1_TAG_NUMBER_MASK|.
+ {false, 0, {0xff, 0x82, 0xff, 0xff, 0xff, 0x7f, 0}},
+ // Tag number does not fit in unsigned.
+ {false, 0, {0xff, 0x90, 0x80, 0x80, 0x80, 0, 0}},
+ // Tag number is not minimally-encoded
+ {false, 0, {0x5f, 0x80, 0x1f, 0}},
+ // Tag number should have used short form.
+ {false, 0, {0x5f, 0x80, 0x1e, 0}},
+ };
+ for (const auto &t : kTests) {
+ SCOPED_TRACE(Bytes(t.in));
+ unsigned tag;
+ CBS cbs, child;
+ CBS_init(&cbs, t.in.data(), t.in.size());
+ ASSERT_EQ(t.ok, !!CBS_get_any_asn1(&cbs, &child, &tag));
+ if (t.ok) {
+ EXPECT_EQ(t.tag, tag);
+ EXPECT_EQ(0u, CBS_len(&child));
+ EXPECT_EQ(0u, CBS_len(&cbs));
+
+ CBS_init(&cbs, t.in.data(), t.in.size());
+ EXPECT_TRUE(CBS_peek_asn1_tag(&cbs, t.tag));
+ EXPECT_FALSE(CBS_peek_asn1_tag(&cbs, t.tag + 1));
+
+ EXPECT_TRUE(CBS_get_asn1(&cbs, &child, t.tag));
+ EXPECT_EQ(0u, CBS_len(&child));
+ EXPECT_EQ(0u, CBS_len(&cbs));
+
+ CBS_init(&cbs, t.in.data(), t.in.size());
+ EXPECT_FALSE(CBS_get_asn1(&cbs, &child, t.tag + 1));
+ }
+ }
+}
+
TEST(CBSTest, GetOptionalASN1Bool) {
static const uint8_t kTrue[] = {0x0a, 3, CBS_ASN1_BOOLEAN, 1, 0xff};
static const uint8_t kFalse[] = {0x0a, 3, CBS_ASN1_BOOLEAN, 1, 0x00};
@@ -416,15 +480,42 @@
}
TEST(CBBTest, ASN1) {
- static const uint8_t kExpected[] = {0x30, 3, 1, 2, 3};
+ static const uint8_t kExpected[] = {
+ // SEQUENCE { 1 2 3 }
+ 0x30, 3, 1, 2, 3,
+ // [4 CONSTRUCTED] { 4 5 6 }
+ 0xa4, 3, 4, 5, 6,
+ // [APPLICATION 30 PRIMITIVE] { 7 8 9 }
+ 0x5e, 3, 7, 8, 9,
+ // [APPLICATION 31 PRIMITIVE] { 10 11 12 }
+ 0x5f, 0x1f, 3, 10, 11, 12,
+ // [PRIVATE 2^29-1 CONSTRUCTED] { 13 14 15 }
+ 0xff, 0x81, 0xff, 0xff, 0xff, 0x7f, 3, 13, 14, 15,
+ };
uint8_t *buf;
size_t buf_len;
bssl::ScopedCBB cbb;
CBB contents, inner_contents;
ASSERT_TRUE(CBB_init(cbb.get(), 0));
- ASSERT_TRUE(CBB_add_asn1(cbb.get(), &contents, 0x30));
+ ASSERT_TRUE(CBB_add_asn1(cbb.get(), &contents, CBS_ASN1_SEQUENCE));
ASSERT_TRUE(CBB_add_bytes(&contents, (const uint8_t *)"\x01\x02\x03", 3));
+ ASSERT_TRUE(
+ CBB_add_asn1(cbb.get(), &contents,
+ CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 4));
+ ASSERT_TRUE(CBB_add_bytes(&contents, (const uint8_t *)"\x04\x05\x06", 3));
+ ASSERT_TRUE(
+ CBB_add_asn1(cbb.get(), &contents,
+ CBS_ASN1_APPLICATION | 30));
+ ASSERT_TRUE(CBB_add_bytes(&contents, (const uint8_t *)"\x07\x08\x09", 3));
+ ASSERT_TRUE(
+ CBB_add_asn1(cbb.get(), &contents,
+ CBS_ASN1_APPLICATION | 31));
+ ASSERT_TRUE(CBB_add_bytes(&contents, (const uint8_t *)"\x0a\x0b\x0c", 3));
+ ASSERT_TRUE(
+ CBB_add_asn1(cbb.get(), &contents,
+ CBS_ASN1_PRIVATE | CBS_ASN1_CONSTRUCTED | 0x1fffffff));
+ ASSERT_TRUE(CBB_add_bytes(&contents, (const uint8_t *)"\x0d\x0e\x0f", 3));
ASSERT_TRUE(CBB_finish(cbb.get(), &buf, &buf_len));
bssl::UniquePtr<uint8_t> scoper(buf);
@@ -432,7 +523,7 @@
std::vector<uint8_t> test_data(100000, 0x42);
ASSERT_TRUE(CBB_init(cbb.get(), 0));
- ASSERT_TRUE(CBB_add_asn1(cbb.get(), &contents, 0x30));
+ ASSERT_TRUE(CBB_add_asn1(cbb.get(), &contents, CBS_ASN1_SEQUENCE));
ASSERT_TRUE(CBB_add_bytes(&contents, test_data.data(), 130));
ASSERT_TRUE(CBB_finish(cbb.get(), &buf, &buf_len));
scoper.reset(buf);
@@ -442,7 +533,7 @@
EXPECT_EQ(Bytes(test_data.data(), 130), Bytes(buf + 3, 130));
ASSERT_TRUE(CBB_init(cbb.get(), 0));
- ASSERT_TRUE(CBB_add_asn1(cbb.get(), &contents, 0x30));
+ ASSERT_TRUE(CBB_add_asn1(cbb.get(), &contents, CBS_ASN1_SEQUENCE));
ASSERT_TRUE(CBB_add_bytes(&contents, test_data.data(), 1000));
ASSERT_TRUE(CBB_finish(cbb.get(), &buf, &buf_len));
scoper.reset(buf);
@@ -452,8 +543,8 @@
EXPECT_EQ(Bytes(test_data.data(), 1000), Bytes(buf + 4, 1000));
ASSERT_TRUE(CBB_init(cbb.get(), 0));
- ASSERT_TRUE(CBB_add_asn1(cbb.get(), &contents, 0x30));
- ASSERT_TRUE(CBB_add_asn1(&contents, &inner_contents, 0x30));
+ ASSERT_TRUE(CBB_add_asn1(cbb.get(), &contents, CBS_ASN1_SEQUENCE));
+ ASSERT_TRUE(CBB_add_asn1(&contents, &inner_contents, CBS_ASN1_SEQUENCE));
ASSERT_TRUE(CBB_add_bytes(&inner_contents, test_data.data(), 100000));
ASSERT_TRUE(CBB_finish(cbb.get(), &buf, &buf_len));
scoper.reset(buf);
@@ -490,6 +581,12 @@
static const uint8_t kIndefBER[] = {0x30, 0x80, 0x01, 0x01, 0x02, 0x00, 0x00};
static const uint8_t kIndefDER[] = {0x30, 0x03, 0x01, 0x01, 0x02};
+ // kIndefBER2 contains a constructed [APPLICATION 31] with an indefinite
+ // length.
+ static const uint8_t kIndefBER2[] = {0x7f, 0x1f, 0x80, 0x01,
+ 0x01, 0x02, 0x00, 0x00};
+ static const uint8_t kIndefDER2[] = {0x7f, 0x1f, 0x03, 0x01, 0x01, 0x02};
+
// kOctetStringBER contains an indefinite length OCTET STRING with two parts.
// These parts need to be concatenated in DER form.
static const uint8_t kOctetStringBER[] = {0x24, 0x80, 0x04, 0x02, 0, 1,
@@ -534,6 +631,8 @@
sizeof(kSimpleBER));
ExpectBerConvert("kIndefBER", kIndefDER, sizeof(kIndefDER), kIndefBER,
sizeof(kIndefBER));
+ ExpectBerConvert("kIndefBER2", kIndefDER2, sizeof(kIndefDER2), kIndefBER2,
+ sizeof(kIndefBER2));
ExpectBerConvert("kOctetStringBER", kOctetStringDER, sizeof(kOctetStringDER),
kOctetStringBER, sizeof(kOctetStringBER));
ExpectBerConvert("kNSSBER", kNSSDER, sizeof(kNSSDER), kNSSBER,
diff --git a/src/crypto/bytestring/cbb.c b/src/crypto/bytestring/cbb.c
index f8f5e0f..b12a66c 100644
--- a/src/crypto/bytestring/cbb.c
+++ b/src/crypto/bytestring/cbb.c
@@ -356,17 +356,20 @@
}
int CBB_add_asn1(CBB *cbb, CBB *out_contents, unsigned tag) {
- if (tag > 0xff ||
- (tag & 0x1f) == 0x1f) {
- // Long form identifier octets are not supported. Further, all current valid
- // tag serializations are 8 bits.
- cbb->base->error = 1;
+ if (!CBB_flush(cbb)) {
return 0;
}
- if (!CBB_flush(cbb) ||
- // |tag|'s representation matches the DER encoding.
- !CBB_add_u8(cbb, (uint8_t)tag)) {
+ // Split the tag into leading bits and tag number.
+ uint8_t tag_bits = (tag >> CBS_ASN1_TAG_SHIFT) & 0xe0;
+ unsigned tag_number = tag & CBS_ASN1_TAG_NUMBER_MASK;
+ if (tag_number >= 0x1f) {
+ // Set all the bits in the tag number to signal high tag number form.
+ if (!CBB_add_u8(cbb, tag_bits | 0x1f) ||
+ !add_base128_integer(cbb, tag_number)) {
+ return 0;
+ }
+ } else if (!CBB_add_u8(cbb, tag_bits | tag_number)) {
return 0;
}
diff --git a/src/crypto/bytestring/cbs.c b/src/crypto/bytestring/cbs.c
index f3fc863..e456330 100644
--- a/src/crypto/bytestring/cbs.c
+++ b/src/crypto/bytestring/cbs.c
@@ -207,18 +207,9 @@
return 1;
}
-static int cbs_get_any_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag,
- size_t *out_header_len, int ber_ok) {
- uint8_t tag, length_byte;
- CBS header = *cbs;
- CBS throwaway;
-
- if (out == NULL) {
- out = &throwaway;
- }
-
- if (!CBS_get_u8(&header, &tag) ||
- !CBS_get_u8(&header, &length_byte)) {
+static int parse_asn1_tag(CBS *cbs, unsigned *out) {
+ uint8_t tag_byte;
+ if (!CBS_get_u8(cbs, &tag_byte)) {
return 0;
}
@@ -229,22 +220,58 @@
// allotted bits), then the tag is more than one byte long and the
// continuation bytes contain the tag number. This parser only supports tag
// numbers less than 31 (and thus single-byte tags).
- if ((tag & 0x1f) == 0x1f) {
- return 0;
+ unsigned tag = ((unsigned)tag_byte & 0xe0) << CBS_ASN1_TAG_SHIFT;
+ unsigned tag_number = tag_byte & 0x1f;
+ if (tag_number == 0x1f) {
+ uint64_t v;
+ if (!parse_base128_integer(cbs, &v) ||
+ // Check the tag number is within our supported bounds.
+ v > CBS_ASN1_TAG_NUMBER_MASK ||
+ // Small tag numbers should have used low tag number form.
+ v < 0x1f) {
+ return 0;
+ }
+ tag_number = (unsigned)v;
}
+ tag |= tag_number;
+
+ *out = tag;
+ return 1;
+}
+
+static int cbs_get_any_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag,
+ size_t *out_header_len, int ber_ok) {
+ CBS header = *cbs;
+ CBS throwaway;
+
+ if (out == NULL) {
+ out = &throwaway;
+ }
+
+ unsigned tag;
+ if (!parse_asn1_tag(&header, &tag)) {
+ return 0;
+ }
if (out_tag != NULL) {
*out_tag = tag;
}
+ uint8_t length_byte;
+ if (!CBS_get_u8(&header, &length_byte)) {
+ return 0;
+ }
+
+ size_t header_len = CBS_len(cbs) - CBS_len(&header);
+
size_t len;
// The format for the length encoding is specified in ITU-T X.690 section
// 8.1.3.
if ((length_byte & 0x80) == 0) {
// Short form length.
- len = ((size_t) length_byte) + 2;
+ len = ((size_t) length_byte) + header_len;
if (out_header_len != NULL) {
- *out_header_len = 2;
+ *out_header_len = header_len;
}
} else {
// The high bit indicate that this is the long form, while the next 7 bits
@@ -256,9 +283,9 @@
if (ber_ok && (tag & CBS_ASN1_CONSTRUCTED) != 0 && num_bytes == 0) {
// indefinite length
if (out_header_len != NULL) {
- *out_header_len = 2;
+ *out_header_len = header_len;
}
- return CBS_get_bytes(cbs, out, 2);
+ return CBS_get_bytes(cbs, out, header_len);
}
// ITU-T X.690 clause 8.1.3.5.c specifies that the value 0xff shall not be
@@ -281,13 +308,13 @@
return 0;
}
len = len32;
- if (len + 2 + num_bytes < len) {
+ if (len + header_len + num_bytes < len) {
// Overflow.
return 0;
}
- len += 2 + num_bytes;
+ len += header_len + num_bytes;
if (out_header_len != NULL) {
- *out_header_len = 2 + num_bytes;
+ *out_header_len = header_len + num_bytes;
}
}
@@ -355,7 +382,10 @@
if (CBS_len(cbs) < 1) {
return 0;
}
- return CBS_data(cbs)[0] == tag_value;
+
+ CBS copy = *cbs;
+ unsigned actual_tag;
+ return parse_asn1_tag(©, &actual_tag) && tag_value == actual_tag;
}
int CBS_get_asn1_uint64(CBS *cbs, uint64_t *out) {
diff --git a/src/crypto/cipher_extra/e_tls.c b/src/crypto/cipher_extra/e_tls.c
index 72754c0..bba22be 100644
--- a/src/crypto/cipher_extra/e_tls.c
+++ b/src/crypto/cipher_extra/e_tls.c
@@ -191,8 +191,7 @@
// block from encrypting the input and split the result between |out| and
// |out_tag|. Then feed the rest.
- const size_t early_mac_len =
- (block_size - (in_len % block_size) % block_size);
+ const size_t early_mac_len = (block_size - (in_len % block_size)) % block_size;
if (early_mac_len != 0) {
assert(len + block_size - early_mac_len == in_len);
uint8_t buf[EVP_MAX_BLOCK_LENGTH];
diff --git a/src/crypto/fipsmodule/ec/ec_key.c b/src/crypto/fipsmodule/ec/ec_key.c
index f64cb21..4e0bcb2 100644
--- a/src/crypto/fipsmodule/ec/ec_key.c
+++ b/src/crypto/fipsmodule/ec/ec_key.c
@@ -233,20 +233,21 @@
const EC_GROUP *EC_KEY_get0_group(const EC_KEY *key) { return key->group; }
int EC_KEY_set_group(EC_KEY *key, const EC_GROUP *group) {
+ // If |key| already has a group, it is an error to switch to another one.
+ if (key->group != NULL) {
+ if (EC_GROUP_cmp(key->group, group, NULL) != 0) {
+ OPENSSL_PUT_ERROR(EC, EC_R_GROUP_MISMATCH);
+ return 0;
+ }
+ return 1;
+ }
+
+ assert(key->priv_key == NULL);
+ assert(key->pub_key == NULL);
+
EC_GROUP_free(key->group);
- // TODO(fork): duplicating the group seems wasteful but see
- // |EC_KEY_set_conv_form|.
key->group = EC_GROUP_dup(group);
- if (key->group == NULL) {
- return 0;
- }
- // XXX: |BN_cmp| is not constant time.
- if (key->priv_key != NULL &&
- (BN_is_negative(key->priv_key) ||
- BN_cmp(key->priv_key, EC_GROUP_get0_order(group)) >= 0)) {
- return 0;
- }
- return 1;
+ return key->group != NULL;
}
const BIGNUM *EC_KEY_get0_private_key(const EC_KEY *key) {
@@ -254,10 +255,14 @@
}
int EC_KEY_set_private_key(EC_KEY *key, const BIGNUM *priv_key) {
+ if (key->group == NULL) {
+ OPENSSL_PUT_ERROR(EC, EC_R_MISSING_PARAMETERS);
+ return 0;
+ }
+
// XXX: |BN_cmp| is not constant time.
- if (key->group != NULL &&
- (BN_is_negative(priv_key) ||
- BN_cmp(priv_key, EC_GROUP_get0_order(key->group)) >= 0)) {
+ if (BN_is_negative(priv_key) ||
+ BN_cmp(priv_key, EC_GROUP_get0_order(key->group)) >= 0) {
OPENSSL_PUT_ERROR(EC, EC_R_WRONG_ORDER);
return 0;
}
@@ -271,6 +276,16 @@
}
int EC_KEY_set_public_key(EC_KEY *key, const EC_POINT *pub_key) {
+ if (key->group == NULL) {
+ OPENSSL_PUT_ERROR(EC, EC_R_MISSING_PARAMETERS);
+ return 0;
+ }
+
+ if (EC_GROUP_cmp(key->group, pub_key->group, NULL) != 0) {
+ OPENSSL_PUT_ERROR(EC, EC_R_GROUP_MISMATCH);
+ return 0;
+ }
+
EC_POINT_free(key->pub_key);
key->pub_key = EC_POINT_dup(pub_key, key->group);
return (key->pub_key == NULL) ? 0 : 1;
diff --git a/src/crypto/fipsmodule/ec/ec_test.cc b/src/crypto/fipsmodule/ec/ec_test.cc
index 8e7a81d..d2cd2af 100644
--- a/src/crypto/fipsmodule/ec/ec_test.cc
+++ b/src/crypto/fipsmodule/ec/ec_test.cc
@@ -305,6 +305,36 @@
EXPECT_NE(0, EC_GROUP_cmp(group.get(), group3.get(), NULL));
}
+TEST(ECTest, SetKeyWithoutGroup) {
+ bssl::UniquePtr<EC_KEY> key(EC_KEY_new());
+ ASSERT_TRUE(key);
+
+ // Private keys may not be configured without a group.
+ EXPECT_FALSE(EC_KEY_set_private_key(key.get(), BN_value_one()));
+
+ // Public keys may not be configured without a group.
+ bssl::UniquePtr<EC_GROUP> group(
+ EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
+ ASSERT_TRUE(group);
+ EXPECT_FALSE(
+ EC_KEY_set_public_key(key.get(), EC_GROUP_get0_generator(group.get())));
+}
+
+TEST(ECTest, GroupMismatch) {
+ bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(NID_secp384r1));
+ ASSERT_TRUE(key);
+ bssl::UniquePtr<EC_GROUP> p256(
+ EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
+ ASSERT_TRUE(p256);
+
+ // Changing a key's group is invalid.
+ EXPECT_FALSE(EC_KEY_set_group(key.get(), p256.get()));
+
+ // Configuring a public key with the wrong group is invalid.
+ EXPECT_FALSE(
+ EC_KEY_set_public_key(key.get(), EC_GROUP_get0_generator(p256.get())));
+}
+
class ECCurveTest : public testing::TestWithParam<EC_builtin_curve> {};
TEST_P(ECCurveTest, SetAffine) {
diff --git a/src/crypto/fipsmodule/modes/internal.h b/src/crypto/fipsmodule/modes/internal.h
index f6ee8f4..68ef4dc 100644
--- a/src/crypto/fipsmodule/modes/internal.h
+++ b/src/crypto/fipsmodule/modes/internal.h
@@ -66,38 +66,6 @@
#define STRICT_ALIGNMENT 0
#endif
-#if defined(__GNUC__) && __GNUC__ >= 2
-static inline uint32_t CRYPTO_bswap4(uint32_t x) {
- return __builtin_bswap32(x);
-}
-
-static inline uint64_t CRYPTO_bswap8(uint64_t x) {
- return __builtin_bswap64(x);
-}
-#elif defined(_MSC_VER)
-OPENSSL_MSVC_PRAGMA(warning(push, 3))
-#include <intrin.h>
-OPENSSL_MSVC_PRAGMA(warning(pop))
-#pragma intrinsic(_byteswap_uint64, _byteswap_ulong)
-static inline uint32_t CRYPTO_bswap4(uint32_t x) {
- return _byteswap_ulong(x);
-}
-
-static inline uint64_t CRYPTO_bswap8(uint64_t x) {
- return _byteswap_uint64(x);
-}
-#else
-static inline uint32_t CRYPTO_bswap4(uint32_t x) {
- x = (x >> 16) | (x << 16);
- x = ((x & 0xff00ff00) >> 8) | ((x & 0x00ff00ff) << 8);
- return x;
-}
-
-static inline uint64_t CRYPTO_bswap8(uint64_t x) {
- return CRYPTO_bswap4(x >> 32) | (((uint64_t)CRYPTO_bswap4(x)) << 32);
-}
-#endif
-
static inline uint32_t GETU32(const void *in) {
uint32_t v;
OPENSSL_memcpy(&v, in, sizeof(v));
diff --git a/src/crypto/fipsmodule/rsa/rsa.c b/src/crypto/fipsmodule/rsa/rsa.c
index 4a84314..ffe2cd0 100644
--- a/src/crypto/fipsmodule/rsa/rsa.c
+++ b/src/crypto/fipsmodule/rsa/rsa.c
@@ -852,6 +852,8 @@
return rsa_default_private_transform(rsa, out, in, len);
}
+int RSA_flags(const RSA *rsa) { return rsa->flags; }
+
int RSA_blinding_on(RSA *rsa, BN_CTX *ctx) {
return 1;
}
diff --git a/src/crypto/fipsmodule/rsa/rsa_impl.c b/src/crypto/fipsmodule/rsa/rsa_impl.c
index c391228..b5a4e51 100644
--- a/src/crypto/fipsmodule/rsa/rsa_impl.c
+++ b/src/crypto/fipsmodule/rsa/rsa_impl.c
@@ -1097,5 +1097,4 @@
// |rsa_default_*| implementation.
OPENSSL_memset(out, 0, sizeof(RSA_METHOD));
out->common.is_static = 1;
- out->flags = RSA_FLAG_CACHE_PUBLIC | RSA_FLAG_CACHE_PRIVATE;
}
diff --git a/src/crypto/internal.h b/src/crypto/internal.h
index 5706414..e6bab02 100644
--- a/src/crypto/internal.h
+++ b/src/crypto/internal.h
@@ -591,6 +591,41 @@
void *obj, CRYPTO_EX_DATA *ad);
+// Endianness conversions.
+
+#if defined(__GNUC__) && __GNUC__ >= 2
+static inline uint32_t CRYPTO_bswap4(uint32_t x) {
+ return __builtin_bswap32(x);
+}
+
+static inline uint64_t CRYPTO_bswap8(uint64_t x) {
+ return __builtin_bswap64(x);
+}
+#elif defined(_MSC_VER)
+OPENSSL_MSVC_PRAGMA(warning(push, 3))
+#include <intrin.h>
+OPENSSL_MSVC_PRAGMA(warning(pop))
+#pragma intrinsic(_byteswap_uint64, _byteswap_ulong)
+static inline uint32_t CRYPTO_bswap4(uint32_t x) {
+ return _byteswap_ulong(x);
+}
+
+static inline uint64_t CRYPTO_bswap8(uint64_t x) {
+ return _byteswap_uint64(x);
+}
+#else
+static inline uint32_t CRYPTO_bswap4(uint32_t x) {
+ x = (x >> 16) | (x << 16);
+ x = ((x & 0xff00ff00) >> 8) | ((x & 0x00ff00ff) << 8);
+ return x;
+}
+
+static inline uint64_t CRYPTO_bswap8(uint64_t x) {
+ return CRYPTO_bswap4(x >> 32) | (((uint64_t)CRYPTO_bswap4(x)) << 32);
+}
+#endif
+
+
// Language bug workarounds.
//
// Most C standard library functions are undefined if passed NULL, even when the
diff --git a/src/crypto/x509/x509_test.cc b/src/crypto/x509/x509_test.cc
index 158fd45..b4cecca 100644
--- a/src/crypto/x509/x509_test.cc
+++ b/src/crypto/x509/x509_test.cc
@@ -835,7 +835,7 @@
/* This ensures the X509 took a reference to |buf|, otherwise this will be a
* reference to free memory and ASAN should notice. */
- ASSERT_EQ(CBS_ASN1_SEQUENCE, enc_pointer[0]);
+ ASSERT_EQ(0x30, enc_pointer[0]);
}
TEST(X509Test, TestFromBufferWithTrailingData) {