Convert base64_test to GTest.
BUG=129
Change-Id: If91d97ea653177d55d5c703f091366ddce24da60
Reviewed-on: https://boringssl-review.googlesource.com/15006
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
diff --git a/crypto/CMakeLists.txt b/crypto/CMakeLists.txt
index 8ea5ea5..0188cda 100644
--- a/crypto/CMakeLists.txt
+++ b/crypto/CMakeLists.txt
@@ -234,6 +234,7 @@
crypto_test
asn1/asn1_test.cc
+ base64/base64_test.cc
bio/bio_test.cc
chacha/chacha_test.cc
constant_time_test.cc
diff --git a/crypto/base64/CMakeLists.txt b/crypto/base64/CMakeLists.txt
index 15ee691..18cf9fe 100644
--- a/crypto/base64/CMakeLists.txt
+++ b/crypto/base64/CMakeLists.txt
@@ -7,14 +7,3 @@
base64.c
)
-
-add_executable(
- base64_test
-
- base64_test.cc
-
- $<TARGET_OBJECTS:test_support>
-)
-
-target_link_libraries(base64_test crypto)
-add_dependencies(all_tests base64_test)
diff --git a/crypto/base64/base64_test.cc b/crypto/base64/base64_test.cc
index bdf3d9a..108c782 100644
--- a/crypto/base64/base64_test.cc
+++ b/crypto/base64/base64_test.cc
@@ -18,11 +18,14 @@
#include <string>
#include <vector>
+#include <gtest/gtest.h>
+
#include <openssl/base64.h>
#include <openssl/crypto.h>
#include <openssl/err.h>
#include "../internal.h"
+#include "../test/test_util.h"
enum encoding_relation {
@@ -100,7 +103,9 @@
"=======\n"},
};
-static const size_t kNumTests = OPENSSL_ARRAY_SIZE(kTestVectors);
+class Base64Test : public testing::TestWithParam<TestVector> {};
+
+INSTANTIATE_TEST_CASE_P(, Base64Test, testing::ValuesIn(kTestVectors));
// RemoveNewlines returns a copy of |in| with all '\n' characters removed.
static std::string RemoveNewlines(const char *in) {
@@ -116,281 +121,187 @@
return ret;
}
-static bool TestEncodeBlock() {
- for (unsigned i = 0; i < kNumTests; i++) {
- const TestVector *t = &kTestVectors[i];
- if (t->relation != canonical) {
- continue;
- }
+TEST_P(Base64Test, EncodeBlock) {
+ const TestVector &t = GetParam();
+ if (t.relation != canonical) {
+ return;
+ }
- const size_t decoded_len = strlen(t->decoded);
+ const size_t decoded_len = strlen(t.decoded);
+ size_t max_encoded_len;
+ ASSERT_TRUE(EVP_EncodedLength(&max_encoded_len, decoded_len));
+
+ std::vector<uint8_t> out_vec(max_encoded_len);
+ uint8_t *out = out_vec.data();
+ size_t len = EVP_EncodeBlock(out, (const uint8_t *)t.decoded, decoded_len);
+
+ std::string encoded(RemoveNewlines(t.encoded));
+ EXPECT_EQ(Bytes(encoded), Bytes(out, len));
+}
+
+TEST_P(Base64Test, DecodeBase64) {
+ const TestVector &t = GetParam();
+ if (t.relation == valid) {
+ // The non-canonical encodings will generally have odd whitespace etc
+ // that |EVP_DecodeBase64| will reject.
+ return;
+ }
+
+ const std::string encoded(RemoveNewlines(t.encoded));
+ std::vector<uint8_t> out_vec(encoded.size());
+ uint8_t *out = out_vec.data();
+
+ size_t len;
+ int ok = EVP_DecodeBase64(out, &len, out_vec.size(),
+ (const uint8_t *)encoded.data(), encoded.size());
+
+ if (t.relation == invalid) {
+ EXPECT_FALSE(ok);
+ } else if (t.relation == canonical) {
+ ASSERT_TRUE(ok);
+ EXPECT_EQ(Bytes(t.decoded), Bytes(out, len));
+ }
+}
+
+TEST_P(Base64Test, DecodeBlock) {
+ const TestVector &t = GetParam();
+ if (t.relation != canonical) {
+ return;
+ }
+
+ std::string encoded(RemoveNewlines(t.encoded));
+
+ std::vector<uint8_t> out_vec(encoded.size());
+ uint8_t *out = out_vec.data();
+
+ // Test that the padding behavior of the deprecated API is preserved.
+ int ret =
+ EVP_DecodeBlock(out, (const uint8_t *)encoded.data(), encoded.size());
+ ASSERT_GE(ret, 0);
+ // EVP_DecodeBlock should ignore padding.
+ ASSERT_EQ(0, ret % 3);
+ size_t expected_len = strlen(t.decoded);
+ if (expected_len % 3 != 0) {
+ ret -= 3 - (expected_len % 3);
+ }
+ EXPECT_EQ(Bytes(t.decoded), Bytes(out, static_cast<size_t>(ret)));
+}
+
+TEST_P(Base64Test, EncodeDecode) {
+ const TestVector &t = GetParam();
+
+ EVP_ENCODE_CTX ctx;
+ const size_t decoded_len = strlen(t.decoded);
+
+ if (t.relation == canonical) {
size_t max_encoded_len;
- if (!EVP_EncodedLength(&max_encoded_len, decoded_len)) {
- fprintf(stderr, "#%u: EVP_EncodedLength failed\n", i);
- return false;
- }
+ ASSERT_TRUE(EVP_EncodedLength(&max_encoded_len, decoded_len));
+ // EVP_EncodeUpdate will output new lines every 64 bytes of output so we
+ // need slightly more than |EVP_EncodedLength| returns. */
+ max_encoded_len += (max_encoded_len + 63) >> 6;
std::vector<uint8_t> out_vec(max_encoded_len);
uint8_t *out = out_vec.data();
- size_t len = EVP_EncodeBlock(out, (const uint8_t *)t->decoded, decoded_len);
- std::string encoded(RemoveNewlines(t->encoded));
- if (len != encoded.size() ||
- OPENSSL_memcmp(out, encoded.data(), len) != 0) {
- fprintf(stderr, "encode(\"%s\") = \"%.*s\", want \"%s\"\n",
- t->decoded, (int)len, (const char*)out, encoded.c_str());
- return false;
- }
- }
+ EVP_EncodeInit(&ctx);
- return true;
-}
-
-static bool TestDecodeBase64() {
- size_t len;
-
- for (unsigned i = 0; i < kNumTests; i++) {
- const TestVector *t = &kTestVectors[i];
-
- if (t->relation == valid) {
- // The non-canonical encodings will generally have odd whitespace etc
- // that |EVP_DecodeBase64| will reject.
- continue;
- }
-
- const std::string encoded(RemoveNewlines(t->encoded));
- std::vector<uint8_t> out_vec(encoded.size());
- uint8_t *out = out_vec.data();
-
- int ok = EVP_DecodeBase64(out, &len, out_vec.size(),
- (const uint8_t *)encoded.data(), encoded.size());
-
- if (t->relation == invalid) {
- if (ok) {
- fprintf(stderr, "decode(\"%s\") didn't fail but should have\n",
- encoded.c_str());
- return false;
- }
- } else if (t->relation == canonical) {
- if (!ok) {
- fprintf(stderr, "decode(\"%s\") failed\n", encoded.c_str());
- return false;
- }
-
- if (len != strlen(t->decoded) ||
- OPENSSL_memcmp(out, t->decoded, len) != 0) {
- fprintf(stderr, "decode(\"%s\") = \"%.*s\", want \"%s\"\n",
- encoded.c_str(), (int)len, (const char*)out, t->decoded);
- return false;
- }
- }
- }
-
- return true;
-}
-
-static bool TestDecodeBlock() {
- for (unsigned i = 0; i < kNumTests; i++) {
- const TestVector *t = &kTestVectors[i];
- if (t->relation != canonical) {
- continue;
- }
-
- std::string encoded(RemoveNewlines(t->encoded));
-
- std::vector<uint8_t> out_vec(encoded.size());
- uint8_t *out = out_vec.data();
-
- // Test that the padding behavior of the deprecated API is preserved.
- int ret =
- EVP_DecodeBlock(out, (const uint8_t *)encoded.data(), encoded.size());
- if (ret < 0) {
- fprintf(stderr, "EVP_DecodeBlock(\"%s\") failed\n", t->encoded);
- return false;
- }
- if (ret % 3 != 0) {
- fprintf(stderr, "EVP_DecodeBlock did not ignore padding\n");
- return false;
- }
- size_t expected_len = strlen(t->decoded);
- if (expected_len % 3 != 0) {
- ret -= 3 - (expected_len % 3);
- }
- if (static_cast<size_t>(ret) != strlen(t->decoded) ||
- OPENSSL_memcmp(out, t->decoded, ret) != 0) {
- fprintf(stderr, "decode(\"%s\") = \"%.*s\", want \"%s\"\n",
- t->encoded, ret, (const char*)out, t->decoded);
- return false;
- }
- }
-
- return true;
-}
-
-static bool TestEncodeDecode() {
- for (unsigned test_num = 0; test_num < kNumTests; test_num++) {
- const TestVector *t = &kTestVectors[test_num];
-
- EVP_ENCODE_CTX ctx;
- const size_t decoded_len = strlen(t->decoded);
-
- if (t->relation == canonical) {
- size_t max_encoded_len;
- if (!EVP_EncodedLength(&max_encoded_len, decoded_len)) {
- fprintf(stderr, "#%u: EVP_EncodedLength failed\n", test_num);
- return false;
- }
-
- // EVP_EncodeUpdate will output new lines every 64 bytes of output so we
- // need slightly more than |EVP_EncodedLength| returns. */
- max_encoded_len += (max_encoded_len + 63) >> 6;
- std::vector<uint8_t> out_vec(max_encoded_len);
- uint8_t *out = out_vec.data();
-
- EVP_EncodeInit(&ctx);
-
- int out_len;
- EVP_EncodeUpdate(&ctx, out, &out_len,
- reinterpret_cast<const uint8_t *>(t->decoded),
- decoded_len);
- size_t total = out_len;
-
- EVP_EncodeFinal(&ctx, out + total, &out_len);
- total += out_len;
-
- if (total != strlen(t->encoded) ||
- OPENSSL_memcmp(out, t->encoded, total) != 0) {
- fprintf(stderr, "#%u: EVP_EncodeUpdate produced different output: '%s' (%u)\n",
- test_num, out, static_cast<unsigned>(total));
- return false;
- }
- }
-
- std::vector<uint8_t> out_vec(strlen(t->encoded));
- uint8_t *out = out_vec.data();
-
- EVP_DecodeInit(&ctx);
int out_len;
- size_t total = 0;
- int ret = EVP_DecodeUpdate(&ctx, out, &out_len,
- reinterpret_cast<const uint8_t *>(t->encoded),
- strlen(t->encoded));
- if (ret != -1) {
- total = out_len;
- ret = EVP_DecodeFinal(&ctx, out + total, &out_len);
- total += out_len;
- }
+ EVP_EncodeUpdate(&ctx, out, &out_len,
+ reinterpret_cast<const uint8_t *>(t.decoded),
+ decoded_len);
+ size_t total = out_len;
- switch (t->relation) {
- case canonical:
- case valid:
- if (ret == -1) {
- fprintf(stderr, "#%u: EVP_DecodeUpdate failed\n", test_num);
- return false;
- }
- if (total != decoded_len ||
- OPENSSL_memcmp(out, t->decoded, decoded_len)) {
- fprintf(stderr, "#%u: EVP_DecodeUpdate produced incorrect output\n",
- test_num);
- return false;
- }
- break;
+ EVP_EncodeFinal(&ctx, out + total, &out_len);
+ total += out_len;
- case invalid:
- if (ret != -1) {
- fprintf(stderr, "#%u: EVP_DecodeUpdate was successful but shouldn't have been\n", test_num);
- return false;
- }
- break;
- }
+ EXPECT_EQ(Bytes(t.encoded), Bytes(out, total));
}
- return true;
+ std::vector<uint8_t> out_vec(strlen(t.encoded));
+ uint8_t *out = out_vec.data();
+
+ EVP_DecodeInit(&ctx);
+ int out_len;
+ size_t total = 0;
+ int ret = EVP_DecodeUpdate(&ctx, out, &out_len,
+ reinterpret_cast<const uint8_t *>(t.encoded),
+ strlen(t.encoded));
+ if (ret != -1) {
+ total = out_len;
+ ret = EVP_DecodeFinal(&ctx, out + total, &out_len);
+ total += out_len;
+ }
+
+ switch (t.relation) {
+ case canonical:
+ case valid:
+ ASSERT_NE(-1, ret);
+ EXPECT_EQ(Bytes(t.decoded), Bytes(out, total));
+ break;
+
+ case invalid:
+ EXPECT_EQ(-1, ret);
+ break;
+ }
}
-static bool TestDecodeUpdateStreaming() {
- for (unsigned test_num = 0; test_num < kNumTests; test_num++) {
- const TestVector *t = &kTestVectors[test_num];
- if (t->relation == invalid) {
- continue;
- }
+TEST_P(Base64Test, DecodeUpdateStreaming) {
+ const TestVector &t = GetParam();
+ if (t.relation == invalid) {
+ return;
+ }
- const size_t encoded_len = strlen(t->encoded);
+ const size_t encoded_len = strlen(t.encoded);
- std::vector<uint8_t> out(encoded_len);
+ std::vector<uint8_t> out(encoded_len);
- for (size_t chunk_size = 1; chunk_size <= encoded_len; chunk_size++) {
- size_t out_len = 0;
- EVP_ENCODE_CTX ctx;
- EVP_DecodeInit(&ctx);
+ for (size_t chunk_size = 1; chunk_size <= encoded_len; chunk_size++) {
+ SCOPED_TRACE(chunk_size);
+ size_t out_len = 0;
+ EVP_ENCODE_CTX ctx;
+ EVP_DecodeInit(&ctx);
- for (size_t i = 0; i < encoded_len;) {
- size_t todo = encoded_len - i;
- if (todo > chunk_size) {
- todo = chunk_size;
- }
-
- int bytes_written;
- int ret = EVP_DecodeUpdate(
- &ctx, out.data() + out_len, &bytes_written,
- reinterpret_cast<const uint8_t *>(t->encoded + i), todo);
- i += todo;
-
- switch (ret) {
- case -1:
- fprintf(stderr, "#%u: EVP_DecodeUpdate returned error\n", test_num);
- return 0;
- case 0:
- out_len += bytes_written;
- if (i == encoded_len ||
- (i + 1 == encoded_len && t->encoded[i] == '\n') ||
- /* If there was an '-' in the input (which means “EOF”) then
- * this loop will continue to test that |EVP_DecodeUpdate| will
- * ignore the remainder of the input. */
- strchr(t->encoded, '-') != nullptr) {
- break;
- }
-
- fprintf(stderr,
- "#%u: EVP_DecodeUpdate returned zero before end of "
- "encoded data\n",
- test_num);
- return 0;
- default:
- out_len += bytes_written;
- }
+ for (size_t i = 0; i < encoded_len;) {
+ size_t todo = encoded_len - i;
+ if (todo > chunk_size) {
+ todo = chunk_size;
}
int bytes_written;
- int ret = EVP_DecodeFinal(&ctx, out.data() + out_len, &bytes_written);
- if (ret == -1) {
- fprintf(stderr, "#%u: EVP_DecodeFinal returned error\n", test_num);
- return 0;
- }
- out_len += bytes_written;
+ int ret = EVP_DecodeUpdate(
+ &ctx, out.data() + out_len, &bytes_written,
+ reinterpret_cast<const uint8_t *>(t.encoded + i), todo);
+ i += todo;
- if (out_len != strlen(t->decoded) ||
- OPENSSL_memcmp(out.data(), t->decoded, out_len) != 0) {
- fprintf(stderr, "#%u: incorrect output\n", test_num);
- return 0;
+ switch (ret) {
+ case -1:
+ FAIL() << "EVP_DecodeUpdate failed";
+ case 0:
+ out_len += bytes_written;
+ if (i == encoded_len ||
+ (i + 1 == encoded_len && t.encoded[i] == '\n') ||
+ /* If there was an '-' in the input (which means “EOF”) then
+ * this loop will continue to test that |EVP_DecodeUpdate| will
+ * ignore the remainder of the input. */
+ strchr(t.encoded, '-') != nullptr) {
+ break;
+ }
+
+ FAIL()
+ << "EVP_DecodeUpdate returned zero before end of encoded data.";
+ case 1:
+ out_len += bytes_written;
+ break;
+ default:
+ FAIL() << "Invalid return value " << ret;
}
}
+
+ int bytes_written;
+ int ret = EVP_DecodeFinal(&ctx, out.data() + out_len, &bytes_written);
+ ASSERT_NE(ret, -1);
+ out_len += bytes_written;
+
+ EXPECT_EQ(Bytes(t.decoded), Bytes(out.data(), out_len));
}
-
- return true;
-}
-
-int main(void) {
- CRYPTO_library_init();
-
- if (!TestEncodeBlock() ||
- !TestDecodeBase64() ||
- !TestDecodeBlock() ||
- !TestDecodeUpdateStreaming() ||
- !TestEncodeDecode()) {
- return 1;
- }
-
- printf("PASS\n");
- return 0;
}
diff --git a/crypto/bytestring/cbs.c b/crypto/bytestring/cbs.c
index 14c55a4..8328b7f 100644
--- a/crypto/bytestring/cbs.c
+++ b/crypto/bytestring/cbs.c
@@ -329,16 +329,13 @@
int CBS_get_asn1_uint64(CBS *cbs, uint64_t *out) {
CBS bytes;
- const uint8_t *data;
- size_t i, len;
-
if (!CBS_get_asn1(cbs, &bytes, CBS_ASN1_INTEGER)) {
return 0;
}
*out = 0;
- data = CBS_data(&bytes);
- len = CBS_len(&bytes);
+ const uint8_t *data = CBS_data(&bytes);
+ size_t len = CBS_len(&bytes);
if (len == 0) {
/* An INTEGER is encoded with at least one octet. */
@@ -355,7 +352,7 @@
return 0;
}
- for (i = 0; i < len; i++) {
+ for (size_t i = 0; i < len; i++) {
if ((*out >> 56) != 0) {
/* Too large to represent as a uint64_t. */
return 0;
diff --git a/crypto/test/test_util.h b/crypto/test/test_util.h
index bce34d4..e03bff4 100644
--- a/crypto/test/test_util.h
+++ b/crypto/test/test_util.h
@@ -21,6 +21,7 @@
#include <string.h>
#include <iosfwd>
+#include <string>
#include "../internal.h"
@@ -37,11 +38,13 @@
Bytes(const char *data_arg, size_t len_arg)
: data(reinterpret_cast<const uint8_t *>(data_arg)), len(len_arg) {}
- Bytes(const char *str)
+ explicit Bytes(const char *str)
: data(reinterpret_cast<const uint8_t *>(str)), len(strlen(str)) {}
+ explicit Bytes(const std::string &str)
+ : data(reinterpret_cast<const uint8_t *>(str.data())), len(str.size()) {}
template <size_t N>
- Bytes(const uint8_t (&array)[N]) : data(array), len(N) {}
+ explicit Bytes(const uint8_t (&array)[N]) : data(array), len(N) {}
const uint8_t *data;
size_t len;
diff --git a/util/all_tests.json b/util/all_tests.json
index ea478ac..49c463a 100644
--- a/util/all_tests.json
+++ b/util/all_tests.json
@@ -1,6 +1,5 @@
[
["crypto/fipsmodule/aes_test", "crypto/fipsmodule/aes/aes_tests.txt"],
- ["crypto/base64/base64_test"],
["crypto/bn/bn_test", "crypto/bn/bn_tests.txt"],
["crypto/bytestring/bytestring_test"],
["crypto/cipher/aead_test", "aes-128-gcm", "crypto/cipher/test/aes_128_gcm_tests.txt"],