diff options
author | Robert Sloan <varomodt@google.com> | 2018-01-03 15:13:14 -0800 |
---|---|---|
committer | Robert Sloan <varomodt@google.com> | 2018-01-03 15:16:16 -0800 |
commit | 0da4395e6883298b793bb05d45e57ed2e03167f9 (patch) | |
tree | ce1ac76289cedf5493948ae3455fe6e55867e260 /src/crypto | |
parent | 558181089d69085101510906bd46e51ade9e20e9 (diff) | |
download | boringssl-0da4395e6883298b793bb05d45e57ed2e03167f9.tar.gz |
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
Diffstat (limited to 'src/crypto')
-rw-r--r-- | src/crypto/asn1/a_int.c | 61 | ||||
-rw-r--r-- | src/crypto/asn1/asn1_test.cc | 28 | ||||
-rw-r--r-- | src/crypto/bytestring/ber.c | 5 | ||||
-rw-r--r-- | src/crypto/bytestring/bytestring_test.cc | 159 | ||||
-rw-r--r-- | src/crypto/bytestring/cbb.c | 19 | ||||
-rw-r--r-- | src/crypto/bytestring/cbs.c | 74 | ||||
-rw-r--r-- | src/crypto/cipher_extra/e_tls.c | 3 | ||||
-rw-r--r-- | src/crypto/fipsmodule/ec/ec_key.c | 45 | ||||
-rw-r--r-- | src/crypto/fipsmodule/ec/ec_test.cc | 30 | ||||
-rw-r--r-- | src/crypto/fipsmodule/modes/internal.h | 32 | ||||
-rw-r--r-- | src/crypto/fipsmodule/rsa/rsa.c | 2 | ||||
-rw-r--r-- | src/crypto/fipsmodule/rsa/rsa_impl.c | 1 | ||||
-rw-r--r-- | src/crypto/internal.h | 35 | ||||
-rw-r--r-- | src/crypto/x509/x509_test.cc | 2 |
14 files changed, 353 insertions, 143 deletions
diff --git a/src/crypto/asn1/a_int.c b/src/crypto/asn1/a_int.c index 8a4edd69..dd74550b 100644 --- a/src/crypto/asn1/a_int.c +++ b/src/crypto/asn1/a_int.c @@ -347,40 +347,45 @@ ASN1_INTEGER *d2i_ASN1_UINTEGER(ASN1_INTEGER **a, const unsigned char **pp, 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) { - OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); - return (0); + + if (!ASN1_INTEGER_set_uint64(a, 0 - (uint64_t) v)) { + return 0; } - d = v; - if (d < 0) { - d = -d; - a->type = V_ASN1_NEG_INTEGER; + + 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; } - 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 accf3ba5..7c114ddf 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 @@ TEST(ASN1Test, LargeTags) { 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 4dc94f6f..bb5e17c4 100644 --- a/src/crypto/bytestring/ber.c +++ b/src/crypto/bytestring/ber.c @@ -29,10 +29,7 @@ static const unsigned kMaxDepth = 2048; // 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 5a6a5c18..1969e73e 100644 --- a/src/crypto/bytestring/bytestring_test.cc +++ b/src/crypto/bytestring/bytestring_test.cc @@ -123,27 +123,27 @@ TEST(CBSTest, GetASN1) { 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 @@ TEST(CBSTest, GetASN1) { 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 @@ TEST(CBSTest, GetASN1) { 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, Misuse) { } 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 @@ TEST(CBBTest, ASN1) { 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 @@ TEST(CBBTest, ASN1) { 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 @@ TEST(CBBTest, ASN1) { 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 @@ TEST(CBSTest, BerConvert) { 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 @@ TEST(CBSTest, BerConvert) { 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 f8f5e0f1..b12a66c2 100644 --- a/src/crypto/bytestring/cbb.c +++ b/src/crypto/bytestring/cbb.c @@ -356,17 +356,20 @@ static int add_base128_integer(CBB *cbb, uint64_t v) { } 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 f3fc8636..e456330f 100644 --- a/src/crypto/bytestring/cbs.c +++ b/src/crypto/bytestring/cbs.c @@ -207,18 +207,9 @@ static int parse_base128_integer(CBS *cbs, uint64_t *out) { 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 @@ static int cbs_get_any_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag, // 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 @@ static int cbs_get_any_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag, 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 @@ static int cbs_get_any_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag, 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 @@ int CBS_peek_asn1_tag(const CBS *cbs, unsigned tag_value) { 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 72754c0f..bba22be5 100644 --- a/src/crypto/cipher_extra/e_tls.c +++ b/src/crypto/cipher_extra/e_tls.c @@ -191,8 +191,7 @@ static int aead_tls_seal_scatter(const EVP_AEAD_CTX *ctx, uint8_t *out, // 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 f64cb21e..4e0bcb22 100644 --- a/src/crypto/fipsmodule/ec/ec_key.c +++ b/src/crypto/fipsmodule/ec/ec_key.c @@ -233,20 +233,21 @@ int EC_KEY_is_opaque(const EC_KEY *key) { 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 @@ const BIGNUM *EC_KEY_get0_private_key(const EC_KEY *key) { } 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 @@ const EC_POINT *EC_KEY_get0_public_key(const EC_KEY *key) { } 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 8e7a81d9..d2cd2afb 100644 --- a/src/crypto/fipsmodule/ec/ec_test.cc +++ b/src/crypto/fipsmodule/ec/ec_test.cc @@ -305,6 +305,36 @@ TEST(ECTest, ArbitraryCurve) { 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 f6ee8f45..68ef4dcc 100644 --- a/src/crypto/fipsmodule/modes/internal.h +++ b/src/crypto/fipsmodule/modes/internal.h @@ -66,38 +66,6 @@ extern "C" { #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 4a843141..ffe2cd08 100644 --- a/src/crypto/fipsmodule/rsa/rsa.c +++ b/src/crypto/fipsmodule/rsa/rsa.c @@ -852,6 +852,8 @@ int RSA_private_transform(RSA *rsa, uint8_t *out, const uint8_t *in, 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 c3912284..b5a4e515 100644 --- a/src/crypto/fipsmodule/rsa/rsa_impl.c +++ b/src/crypto/fipsmodule/rsa/rsa_impl.c @@ -1097,5 +1097,4 @@ DEFINE_METHOD_FUNCTION(RSA_METHOD, RSA_default_method) { // |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 57064142..e6bab02b 100644 --- a/src/crypto/internal.h +++ b/src/crypto/internal.h @@ -591,6 +591,41 @@ OPENSSL_EXPORT void CRYPTO_free_ex_data(CRYPTO_EX_DATA_CLASS *ex_data_class, 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 158fd458..b4cecca2 100644 --- a/src/crypto/x509/x509_test.cc +++ b/src/crypto/x509/x509_test.cc @@ -835,7 +835,7 @@ TEST(X509Test, TestFromBuffer) { /* 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) { |