Skip to content

Commit

Permalink
Add variable-size IO test
Browse files Browse the repository at this point in the history
  • Loading branch information
WillChilds-Klein committed Sep 30, 2024
1 parent 9b7deca commit df434b2
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 9 deletions.
96 changes: 92 additions & 4 deletions crypto/pkcs7/bio/bio_deprecated_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#include <openssl/bio.h>
#include <openssl/bytestring.h>
#include <openssl/rand.h>
#include <openssl/x509.h>

#include "../../test/test_util.h"
Expand Down Expand Up @@ -37,7 +38,7 @@ INSTANTIATE_TEST_SUITE_P(
[](const testing::TestParamInfo<MessageDigestParams> &params)
-> std::string { return params.param.name; });

TEST_P(BIODeprecatedTest, MessageDigest) {
TEST_P(BIODeprecatedTest, MessageDigestBasic) {
uint8_t message[1024 * 8];
uint8_t buf[16 * 1024];
std::vector<uint8_t> message_vec;
Expand All @@ -53,8 +54,6 @@ TEST_P(BIODeprecatedTest, MessageDigest) {
const EVP_MD *md = GetParam().md();
ASSERT_TRUE(md);

// TODO [childw] bad input
// - ptr to non-const MD
bio_md.reset(BIO_new(BIO_f_md()));
ASSERT_TRUE(bio_md);
EXPECT_TRUE(BIO_set_md(bio_md.get(), (EVP_MD *)md));
Expand Down Expand Up @@ -128,6 +127,95 @@ TEST_P(BIODeprecatedTest, MessageDigest) {
EXPECT_NE(Bytes(buf_vec.data(), buf_vec.size()), Bytes(buf, digest_len));
bio_md.release(); // |bio| took ownership
bio_mem.release(); // |bio| took ownership
}

TEST_P(BIODeprecatedTest, MessageDigestRandomized) {
uint8_t message_buf[8 * 1024];
uint8_t digest_buf[EVP_MAX_MD_SIZE];
std::vector<uint8_t> message;
std::vector<uint8_t> expected_digest;
bssl::UniquePtr<BIO> bio;
bssl::UniquePtr<BIO> bio_md;
bssl::UniquePtr<BIO> bio_mem;
bssl::UniquePtr<EVP_MD_CTX> ctx;
int pos = -1;


// Callback tests
const EVP_MD *md = GetParam().md();
ASSERT_TRUE(md);

const size_t block_size = EVP_MD_block_size(md);
std::vector<std::vector<size_t>> io_patterns = {
{0},
{1},
{},
{8, 8, 8, 8},
{block_size - 1, 1, block_size + 1, block_size, block_size - 1},
{4, 1, 5, 3, 2, 0, 1, sizeof(message_buf), 133, 4555, 22, 4, 7964, 1234},
};

for (auto io_pattern : io_patterns) {
message.clear();
expected_digest.clear();
ctx.reset(EVP_MD_CTX_new());
EVP_DigestInit_ex(ctx.get(), md, NULL);
// Construct overall message and its expected expected_digest
for (auto io_size : io_pattern) {
ASSERT_LE(io_size, sizeof(message_buf));
RAND_bytes(message_buf, io_size);
message.insert(message.end(), &message_buf[0], &message_buf[io_size]);
}
EVP_DigestUpdate(ctx.get(), message.data(), message.size());
unsigned digest_size;
EVP_DigestFinal_ex(ctx.get(), digest_buf, &digest_size);
ASSERT_EQ(EVP_MD_CTX_size(ctx.get()), digest_size);
expected_digest.insert(expected_digest.begin(), &digest_buf[0],
&digest_buf[digest_size]);
OPENSSL_cleanse(digest_buf, sizeof(digest_buf));

// Write-through expected_digest BIO, check against expectation
bio_md.reset(BIO_new(BIO_f_md()));
ASSERT_TRUE(bio_md);
EXPECT_TRUE(BIO_set_md(bio_md.get(), (void *)md));
bio_mem.reset(BIO_new(BIO_s_mem()));
ASSERT_TRUE(bio_mem);
bio.reset(BIO_push(bio_md.get(), bio_mem.get()));
ASSERT_TRUE(bio);
pos = 0;
for (auto io_size : io_pattern) {
int wsize = BIO_write(bio.get(), (char *)(message.data() + pos), io_size);
EXPECT_EQ((int)io_size, wsize);
pos += io_size;
}
digest_size =
BIO_gets(bio_md.get(), (char *)digest_buf, sizeof(digest_buf));
ASSERT_EQ(EVP_MD_CTX_size(ctx.get()), digest_size);
EXPECT_EQ(Bytes(expected_digest.data(), expected_digest.size()),
Bytes(digest_buf, digest_size));
OPENSSL_cleanse(digest_buf, sizeof(digest_buf));
bio_md.release(); // |bio| took ownership
bio_mem.release(); // |bio| took ownership

// Read-through expected_digest BIO, check against expectation
bio_md.reset(BIO_new(BIO_f_md()));
ASSERT_TRUE(bio_md);
EXPECT_TRUE(BIO_set_md(bio_md.get(), (void *)md));
bio_mem.reset(BIO_new_mem_buf(message.data(), message.size()));
ASSERT_TRUE(bio_mem);
bio.reset(BIO_push(bio_md.get(), bio_mem.get()));
ASSERT_TRUE(bio);
pos = 0;
for (auto io_size : io_pattern) {
int rsize = BIO_read(bio.get(), message_buf, io_size);
EXPECT_EQ((int)io_size, rsize);
}
digest_size =
BIO_gets(bio_md.get(), (char *)digest_buf, sizeof(digest_buf));
ASSERT_EQ(EVP_MD_CTX_size(ctx.get()), digest_size);
EXPECT_EQ(Bytes(expected_digest.data(), expected_digest.size()),
Bytes(digest_buf, digest_size));
OPENSSL_cleanse(digest_buf, sizeof(digest_buf));
bio_md.release(); // |bio| took ownership
bio_mem.release(); // |bio| took ownership
}
}
6 changes: 2 additions & 4 deletions crypto/pkcs7/bio/md.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,7 @@ static int md_new(BIO *b) {
}

static int md_free(BIO *b) {
if (b == NULL) {
return 0;
}
GUARD_PTR(b);
EVP_MD_CTX_free(BIO_get_data(b));
BIO_set_data(b, NULL);
BIO_set_init(b, 0);
Expand All @@ -60,7 +58,7 @@ static int md_read(BIO *b, char *out, int outl) {
ctx = BIO_get_data(b);
next = BIO_next(b);

if ((ctx == NULL) || (next == NULL)) {
if ((ctx == NULL) || (next == NULL) || outl <= 0) {
return 0;
}

Expand Down
7 changes: 6 additions & 1 deletion crypto/pkcs7/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -199,9 +199,14 @@ int pkcs7_add_signed_data(CBB *out,
int (*signer_infos_cb)(CBB *out, const void *arg),
const void *arg);

// TODO [childw]
// BIO_f_md is used internally by the pkcs7 module. It is not recommended
// for external use.
OPENSSL_EXPORT const BIO_METHOD *BIO_f_md(void);

// BIO_get_md_ctx writes a reference of |b|'s EVP_MD_CTX* to |*mdcp|
#define BIO_get_md_ctx(b, mdcp) BIO_ctrl(b, BIO_C_GET_MD_CTX, 0, mdcp)

// BIO_set_md set's |b|'s EVP_MD* to |md|
#define BIO_set_md(b, md) BIO_ctrl(b, BIO_C_SET_MD, 0, md)

#if defined(__cplusplus)
Expand Down

0 comments on commit df434b2

Please sign in to comment.