Skip to content

Commit

Permalink
Merge branch 'aws:main' into pkcs7-ctors
Browse files Browse the repository at this point in the history
  • Loading branch information
WillChilds-Klein authored Aug 8, 2024
2 parents 9c31551 + 8d5e8c1 commit 6016c77
Show file tree
Hide file tree
Showing 111 changed files with 7,237 additions and 3,242 deletions.
4 changes: 3 additions & 1 deletion .github/docker_images/cmake_build_versions/cmake_build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ set -ex -o pipefail

echo "Building CMake Version: ${CMAKE_VERSION:-unknown}"

NUM_CPU_THREADS=$(grep -c ^processor /proc/cpuinfo)

# At the moment this works fine for all versions, in the future build logic can be modified to
# look at it ${CMAKE_VERSION}.
./configure --prefix=/opt/cmake --system-curl --system-libarchive
make
make -j"${NUM_CPU_THREADS}"
make install
8 changes: 7 additions & 1 deletion crypto/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,8 @@ add_library(
lhash/lhash.c
mem.c
ml_kem/ml_kem_512_ipd.c
ml_kem/ml_kem_768_ipd.c
ml_kem/ml_kem_1024_ipd.c
ml_kem/ml_kem.c
obj/obj.c
obj/obj_xref.c
Expand Down Expand Up @@ -700,7 +702,11 @@ else()
build_libcrypto(crypto $<TARGET_OBJECTS:fipsmodule>)
endif()

if(NOT ANDROID)
# CMAKE_SYSTEM_NAME is "Generic" for embedded OSes:
# https://cmake.org/cmake/help/book/mastering-cmake/chapter/Cross%20Compiling%20With%20CMake.html#toolchain-files
#
# For now we assume embedded OSes do not have threads.
if(NOT (ANDROID OR CMAKE_SYSTEM_NAME STREQUAL "Generic"))
find_package(Threads REQUIRED)
target_link_libraries(crypto PUBLIC Threads::Threads)
endif()
Expand Down
68 changes: 59 additions & 9 deletions crypto/bio/bio.c
Original file line number Diff line number Diff line change
Expand Up @@ -212,17 +212,26 @@ int BIO_gets(BIO *bio, char *buf, int len) {
OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
return -2;
}
int ret = 0;
if (HAS_CALLBACK(bio)) {
ret = (int)bio->callback_ex(bio, BIO_CB_GETS, buf, len, 0, 0L, 1L, NULL);
if (ret <= 0) {
return ret;
}
}
if (!bio->init) {
OPENSSL_PUT_ERROR(BIO, BIO_R_UNINITIALIZED);
return -2;
}
if (len <= 0) {
return 0;
}
int ret = bio->method->bgets(bio, buf, len);
ret = bio->method->bgets(bio, buf, len);
if (ret > 0) {
bio->num_read += ret;
}
ret = call_bio_callback_with_processed(bio, BIO_CB_GETS | BIO_CB_RETURN, buf,
len, ret);
return ret;
}

Expand Down Expand Up @@ -299,13 +308,42 @@ int BIO_write_all(BIO *bio, const void *data, size_t len) {
}

int BIO_puts(BIO *bio, const char *in) {
size_t len = strlen(in);
if (len > INT_MAX) {
// |BIO_write| and the return value both assume the string fits in |int|.
OPENSSL_PUT_ERROR(BIO, ERR_R_OVERFLOW);
return -1;
// Check for bwrites here since we use that if bputs is NULL
if (bio == NULL || bio->method == NULL || (bio->method->bwrite == NULL &&
bio->method->bputs == NULL)) {
OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
return -2;
}
return BIO_write(bio, in, (int)len);
int ret = 0;
if(HAS_CALLBACK(bio)) {
ret = (int)bio->callback_ex(bio, BIO_CB_PUTS, in, 0, 0, 0L, 1L, NULL);
if (ret <= 0) {
return ret;
}
}

if (!bio->init) {
OPENSSL_PUT_ERROR(BIO, BIO_R_UNINITIALIZED);
return -2;
}
if (bio->method->bputs != NULL) {
ret = bio->method->bputs(bio, in);
} else {
const size_t len = strlen(in);
if (len > INT_MAX) {
// |BIO_write| and the return value both assume the string fits in |int|.
OPENSSL_PUT_ERROR(BIO, ERR_R_OVERFLOW);
return -1;
}
ret = bio->method->bwrite(bio, in, len);
}
if (ret > 0) {
bio->num_write += ret;
}
ret = call_bio_callback_with_processed(bio, BIO_CB_PUTS | BIO_CB_RETURN,
in, 0, ret);

return ret;
}

int BIO_flush(BIO *bio) {
Expand All @@ -321,8 +359,20 @@ long BIO_ctrl(BIO *bio, int cmd, long larg, void *parg) {
OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
return -2;
}
long ret = 0;
if (HAS_CALLBACK(bio)) {
ret = bio->callback_ex(bio, BIO_CB_CTRL, parg, 0, cmd, larg, 1L, NULL);
if (ret <= 0) {
return ret;
}
}

return bio->method->ctrl(bio, cmd, larg, parg);
ret = bio->method->ctrl(bio, cmd, larg, parg);
if (HAS_CALLBACK(bio)) {
ret = bio->callback_ex(bio, BIO_CB_CTRL | BIO_CB_RETURN, parg, 0, cmd, larg,
ret, NULL);
}
return ret;
}

char *BIO_ptr_ctrl(BIO *b, int cmd, long larg) {
Expand Down Expand Up @@ -838,7 +888,7 @@ void BIO_set_shutdown(BIO *bio, int shutdown) { bio->shutdown = shutdown; }
int BIO_get_shutdown(BIO *bio) { return bio->shutdown; }

int BIO_meth_set_puts(BIO_METHOD *method, int (*puts)(BIO *, const char *)) {
// Ignore the parameter. We implement |BIO_puts| using |BIO_write|.
method->bputs = puts;
return 1;
}

Expand Down
180 changes: 180 additions & 0 deletions crypto/bio/bio_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1095,3 +1095,183 @@ TEST(BIOTest, ReadWriteEx) {
EXPECT_FALSE(BIO_read_ex(bio.get(), nullptr, 0, &read));
EXPECT_EQ(read, (size_t)0);
}

TEST(BIOTest, TestPutsAsWrite) {
// By default, |BIO_puts| acts as |BIO_write|.
bssl::UniquePtr<BIO> bio(BIO_new(BIO_s_mem()));
ASSERT_TRUE(bio);

// Test basic puts and read
uint8_t buf[32];
EXPECT_EQ(12, BIO_puts(bio.get(), "hello world\n"));
EXPECT_EQ(12, BIO_read(bio.get(), buf, sizeof(buf)));
}

namespace {
// Define custom BIO and BIO_METHODS to test BIO_puts without write
static int customPuts(BIO *b, const char *in) {
return 0;
}
static int customNew(BIO *b) {
b->init=1;
return 1;
}
static const BIO_METHOD custom_method = {
BIO_TYPE_NONE, "CustomBioMethod", NULL /* write */,
NULL, customPuts, NULL,
NULL, customNew, NULL,
NULL
};

static const BIO_METHOD *BIO_cust(void) { return &custom_method; }

TEST(BIOTest, TestCustomPuts) {
bssl::UniquePtr<BIO> bio(BIO_new(BIO_cust()));
ASSERT_TRUE(bio);

ASSERT_EQ(0, BIO_puts(bio.get(), "hello world"));

// Test setting new puts method by creating a new BIO
bssl::UniquePtr<BIO_METHOD> method(BIO_meth_new(0, nullptr));
ASSERT_TRUE(method);
ASSERT_TRUE(BIO_meth_set_create(
method.get(), [](BIO *b) -> int {
BIO_set_init(b, 1);
return 1;
}));
ASSERT_TRUE(BIO_meth_set_puts(
method.get(), [](BIO *b, const char *in) -> int {
return 100;
}
));
bssl::UniquePtr<BIO> bio1(BIO_new(method.get()));
ASSERT_TRUE(bio1);
ASSERT_TRUE(bio1.get()->method->bputs);
ASSERT_FALSE(bio1.get()->method->bwrite);
// The new BIO_puts should only return 100
ASSERT_EQ(100, BIO_puts(bio1.get(), "hello world"));
}

TEST(BIOTest, TestPutsNullMethod) {
// Create new BIO to test when neither puts nor write is set
bssl::UniquePtr<BIO_METHOD> method(BIO_meth_new(0, nullptr));
ASSERT_TRUE(method);
ASSERT_TRUE(BIO_meth_set_create(
method.get(), [](BIO *b) -> int {
BIO_set_init(b, 1);
return 1;
}));
bssl::UniquePtr<BIO> bio(BIO_new(method.get()));
ASSERT_TRUE(bio);

ASSERT_FALSE(bio.get()->method->bputs);
ASSERT_FALSE(bio.get()->method->bwrite);
ASSERT_EQ(-2, BIO_puts(bio.get(), "hello world"));
}
} //namespace

TEST(BIOTest, TestPutsCallbacks) {
bio_callback_cleanup();
BIO* bio = BIO_new(BIO_s_mem());
ASSERT_TRUE(bio);

BIO_set_callback_ex(bio, bio_cb_ex);

EXPECT_EQ(TEST_DATA_WRITTEN, BIO_puts(bio, "12345"));

ASSERT_EQ(param_oper_ex[0], BIO_CB_PUTS);
ASSERT_EQ(param_oper_ex[1], BIO_CB_PUTS | BIO_CB_RETURN);

ASSERT_EQ(param_argp_ex[0], param_argp_ex[1]);
ASSERT_EQ(param_ret_ex[0], 1);
ASSERT_EQ(param_ret_ex[1], TEST_DATA_WRITTEN);

// len unused in puts callback
ASSERT_FALSE(param_len_ex[0]);
ASSERT_FALSE(param_len_ex[1]);

ASSERT_EQ(param_argi_ex[0], 0);
ASSERT_EQ(param_argi_ex[1], 0);
ASSERT_EQ(param_argl_ex[0], 0);
ASSERT_EQ(param_argl_ex[1], 0);

ASSERT_EQ(param_processed_ex[0], 0u);
ASSERT_EQ(param_processed_ex[1], 5u);

// The mock should be "full" at this point
ASSERT_EQ(test_count_ex, CB_TEST_COUNT);

bio_callback_cleanup();
ASSERT_EQ(BIO_free(bio), 1);
}

TEST(BIOTest, TestGetsCallback) {
bio_callback_cleanup();

BIO* bio = BIO_new(BIO_s_mem());
ASSERT_TRUE(bio);
// write data to BIO, then set callback
EXPECT_EQ(TEST_DATA_WRITTEN, BIO_write(bio, "12345", TEST_DATA_WRITTEN));
char buf[TEST_BUF_LEN];
BIO_set_callback_ex(bio, bio_cb_ex);

ASSERT_EQ(TEST_DATA_WRITTEN, BIO_gets(bio, buf, sizeof(buf)));

ASSERT_EQ(param_oper_ex[0], BIO_CB_GETS);
ASSERT_EQ(param_oper_ex[1], BIO_CB_GETS | BIO_CB_RETURN);

ASSERT_EQ(param_argp_ex[0], param_argp_ex[1]);
ASSERT_EQ(param_ret_ex[0], 1);
ASSERT_EQ(param_ret_ex[1], TEST_DATA_WRITTEN);

ASSERT_EQ(param_len_ex[0], (size_t)TEST_BUF_LEN);
ASSERT_EQ(param_len_ex[1], (size_t)TEST_BUF_LEN);

ASSERT_EQ(param_argi_ex[0], 0);
ASSERT_EQ(param_argi_ex[1], 0);
ASSERT_EQ(param_argl_ex[0], 0);
ASSERT_EQ(param_argl_ex[1], 0);

ASSERT_EQ(param_processed_ex[0], 0u);
ASSERT_EQ(param_processed_ex[1], 5u);

ASSERT_EQ(test_count_ex, CB_TEST_COUNT);

bio_callback_cleanup();
ASSERT_EQ(BIO_free(bio), 1);
}

TEST(BIOTest, TestCtrlCallback) {
bio_callback_cleanup();

BIO* bio = BIO_new(BIO_s_mem());
ASSERT_TRUE(bio);
BIO_set_callback_ex(bio, bio_cb_ex);

char buf[TEST_BUF_LEN];
// Test BIO_ctrl. This is not normally called directly so we can use one of
// the macros such as BIO_reset to test it
ASSERT_EQ(BIO_reset(bio), 1);

ASSERT_EQ(param_oper_ex[0], BIO_CB_CTRL);
ASSERT_EQ(param_oper_ex[1], BIO_CB_CTRL | BIO_CB_RETURN);

// argi in this case in the cmd sent to the ctrl method
ASSERT_EQ(param_argi_ex[0], BIO_CTRL_RESET);
ASSERT_EQ(param_argi_ex[1], BIO_CTRL_RESET);

// BIO_ctrl of a memory bio sets ret to 1 when it calls the reset method
ASSERT_EQ(param_ret_ex[0], 1);
ASSERT_EQ(param_ret_ex[1], 1);

// processed is unused in ctrl
ASSERT_EQ(param_processed_ex[0], 0u);
ASSERT_EQ(param_processed_ex[1], 0u);

bio_callback_cleanup();
// check that BIO_reset was called correctly
ASSERT_EQ(BIO_gets(bio, buf, sizeof(buf)), 0);

bio_callback_cleanup();
ASSERT_EQ(BIO_free(bio), 1);
}
Loading

0 comments on commit 6016c77

Please sign in to comment.