Skip to content

Commit

Permalink
rsa and md5 tools
Browse files Browse the repository at this point in the history
  • Loading branch information
ecdeye committed Jul 25, 2024
1 parent b7d7a99 commit 5566a44
Show file tree
Hide file tree
Showing 9 changed files with 571 additions and 6 deletions.
4 changes: 4 additions & 0 deletions tests/ci/run_openssl_comparison_tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,9 @@ for branch in "${!openssl_branches[@]}"; do
export OPENSSL_TOOL_PATH="${install_dir}/openssl-${branch}/bin/openssl"
echo "Running X509ComparisonTests against OpenSSL ${branch}"
LD_LIBRARY_PATH="${install_dir}/openssl-${branch}/${openssl_branches[$branch]}" "${BUILD_ROOT}/tool-openssl/tool_openssl_test" --gtest_filter=X509ComparisonTest.*
echo "Running RSAComparisonTests against OpenSSL ${branch}"
LD_LIBRARY_PATH="${install_dir}/openssl-${branch}/${openssl_branches[$branch]}" "${BUILD_ROOT}/tool-openssl/tool_openssl_test" --gtest_filter=RSAComparisonTest.*
echo "Running MD5ComparisonTests against OpenSSL ${branch}"
LD_LIBRARY_PATH="${install_dir}/openssl-${branch}/${openssl_branches[$branch]}" "${BUILD_ROOT}/tool-openssl/tool_openssl_test" --gtest_filter=MD5ComparisonTest.*
done

8 changes: 7 additions & 1 deletion tool-openssl/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ add_executable(
../tool/file.cc
tool.cc
x509.cc
rsa.cc
md5.cc
)

target_include_directories(openssl PUBLIC ${PROJECT_SOURCE_DIR}/include)
Expand Down Expand Up @@ -43,10 +45,14 @@ if(BUILD_TESTING)
add_executable(
tool_openssl_test

x509_test.cc
../tool/args.cc
../tool/file.cc
x509_test.cc
rsa_test.cc
md5_test.cc
x509.cc
rsa.cc
md5.cc
)

target_link_libraries(tool_openssl_test boringssl_gtest_main ssl crypto)
Expand Down
11 changes: 8 additions & 3 deletions tool-openssl/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@
*Files expected to change*

Current status:
* Contains initial implementation for OpenSSL x509 tool, options -in -out, -req, -signkey, -modulus, -days, -dates,
-checkend, -noout (x509.cc), and unit test (x509_test.cc)
* OpenSSL rsa tool yet to be implemented
* Contains initial implementation for OpenSSL x509, rsa, and md5 tools
* x509 options: -in -out, -req, -signkey, -modulus, -days, -dates,
-checkend, -noout (x509.cc)
* rsa options: -in, -out, -noout, -modulus (rsa.cc)
* md5 options: N/A (md5.cc)
* Unit, integration, and OpenSSL comparison tests (x509_test.cc, rsa_test.cc, md5_test.cc)
* OpenSSL comparison tests require environment variables for both AWS-LC and OpenSSL tools

2 changes: 2 additions & 0 deletions tool-openssl/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,7 @@ tool_func_t FindTool(const std::string &name);
tool_func_t FindTool(int argc, char **argv, int &starting_arg);

bool X509Tool(const args_list_t &args);
bool rsaTool(const args_list_t &args);
bool md5Tool(const args_list_t &args);

#endif //INTERNAL_H
49 changes: 49 additions & 0 deletions tool-openssl/md5.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0 OR ISC

#include <openssl/md5.h>
#include <iostream>
#include "internal.h"

static const argument_t kArguments[] = {
{ "-help", kBooleanArgument, "Display option summary" },
{ "", kOptionalArgument, "" }
};

// Map arguments using tool/args.cc
bool md5Tool(const args_list_t &args) {
args_map_t parsed_args;
if (!ParseKeyValueArguments(&parsed_args, args, kArguments)) {
PrintUsage(kArguments);
return false;
}

bool help = false;
GetBoolArgument(&help, "-help", parsed_args);

if (help) {
PrintUsage(kArguments);
return false;
}

// Read input from stdin
std::string input;
std::getline(std::cin, input);

if (input.empty()) {
fprintf(stderr, "Error: no input provided\n");
return false;
}

unsigned char md5_digest[MD5_DIGEST_LENGTH];
MD5(reinterpret_cast<const unsigned char*>(input.c_str()), input.length(), md5_digest);

printf("MD5(stdin)= ");
for (int i = 0; i < MD5_DIGEST_LENGTH; ++i) {
printf("%02x", md5_digest[i]);
}
printf("\n");

return true;
}

109 changes: 109 additions & 0 deletions tool-openssl/md5_test.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0 OR ISC

#include "openssl/rsa.h"
#include <gtest/gtest.h>
#include <openssl/pem.h>
#include "internal.h"
#include <fstream>
#include <cctype>


#ifdef _WIN32
#include <windows.h>
#ifndef PATH_MAX
#define PATH_MAX MAX_PATH
#endif
#else
#include <unistd.h>
#ifndef PATH_MAX
#define PATH_MAX 4096
#endif
#endif

size_t createTempFILEpath(char buffer[PATH_MAX]);

void RemoveFile(const char* path);

std::string ReadFileToString(const std::string& file_path);

RSA* CreateRSAKey();


// -------------------- MD5 OpenSSL Comparison Test ---------------------------

// Comparison tests cannot run without set up of environment variables:
// AWSLC_TOOL_PATH and OPENSSL_TOOL_PATH.
// TODO: add instructions in readme

class MD5ComparisonTest : public ::testing::Test {
protected:
void SetUp() override {

// Skip gtests if env variables not set
tool_executable_path = getenv("AWSLC_TOOL_PATH");
openssl_executable_path = getenv("OPENSSL_TOOL_PATH");
if (tool_executable_path == nullptr || openssl_executable_path == nullptr) {
GTEST_SKIP() << "Skipping test: AWSLC_TOOL_PATH and/or OPENSSL_TOOL_PATH environment variables are not set";
}

ASSERT_GT(createTempFILEpath(in_path), 0u);
ASSERT_GT(createTempFILEpath(out_path_tool), 0u);
ASSERT_GT(createTempFILEpath(out_path_openssl), 0u);

rsa.reset(CreateRSAKey());
ASSERT_TRUE(rsa);

ScopedFILE in_file(fopen(in_path, "wb"));
ASSERT_TRUE(in_file);
ASSERT_TRUE(PEM_write_RSAPrivateKey(in_file.get(), rsa.get(), nullptr, nullptr, 0, nullptr, nullptr));
}

void RunCommandsAndCompareOutput(const std::string &tool_command, const std::string &openssl_command) {
int tool_result = system(tool_command.c_str());
ASSERT_EQ(tool_result, 0) << "AWS-LC tool command failed: " << tool_command;

int openssl_result = system(openssl_command.c_str());
ASSERT_EQ(openssl_result, 0) << "OpenSSL command failed: " << openssl_command;

std::ifstream tool_output(out_path_tool);
this->tool_output_str = std::string((std::istreambuf_iterator<char>(tool_output)), std::istreambuf_iterator<char>());
std::ifstream openssl_output(out_path_openssl);
this->openssl_output_str = std::string((std::istreambuf_iterator<char>(openssl_output)), std::istreambuf_iterator<char>());

std::cout << "AWS-LC tool output:" << std::endl << this->tool_output_str << std::endl;
std::cout << "OpenSSL output:" << std::endl << this->openssl_output_str << std::endl;
}


void TearDown() override {
if (tool_executable_path != nullptr && openssl_executable_path != nullptr) {
RemoveFile(in_path);
RemoveFile(out_path_tool);
RemoveFile(out_path_openssl);
}
}

char in_path[PATH_MAX];
char out_path_tool[PATH_MAX];
char out_path_openssl[PATH_MAX];
bssl::UniquePtr<RSA> rsa;
const char* tool_executable_path;
const char* openssl_executable_path;
std::string tool_output_str;
std::string openssl_output_str;
};

const std::string MODULUS = "MD5(stdin)= ";

// Test against OpenSSL output "openssl rsa -noout -modulus -in file | openssl md5"
TEST_F(MD5ComparisonTest, MD5ToolCompareOpenSSL) {
std::string tool_command = std::string(tool_executable_path) + " rsa -noout -modulus -in " + in_path + " | openssl md5 > " + out_path_tool;
std::string openssl_command = std::string(openssl_executable_path) + " rsa -noout -modulus -in " + in_path + " | openssl md5 > " + out_path_openssl;

RunCommandsAndCompareOutput(tool_command, openssl_command);
ASSERT_EQ(tool_output_str.compare(0, MODULUS.size(), MODULUS), 0);
ASSERT_EQ(openssl_output_str.compare(0, MODULUS.size(), MODULUS), 0);
ASSERT_EQ(tool_output_str.size(), openssl_output_str.size());

}
102 changes: 102 additions & 0 deletions tool-openssl/rsa.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0 OR ISC

#include <openssl/rsa.h>
#include <openssl/pem.h>
#include "internal.h"

static const argument_t kArguments[] = {
{ "-help", kBooleanArgument, "Display option summary" },
{ "-in", kOptionalArgument, "RSA key input file" },
{ "-out", kOptionalArgument, "Output file to write to" },
{ "-noout", kBooleanArgument, "Prevents output of the encoded version of the RSA key" },
{ "-modulus", kBooleanArgument, "Prints out the value of the modulus of the RSA key" },
{ "", kOptionalArgument, "" }
};

// Map arguments using tool/args.cc
bool rsaTool(const args_list_t &args) {
args_map_t parsed_args;
if (!ParseKeyValueArguments(&parsed_args, args, kArguments)) {
PrintUsage(kArguments);
return false;
}

std::string in_path, out_path;
bool noout = false, modulus = false;
bool help = false;

GetBoolArgument(&help, "-help", parsed_args);
GetString(&in_path, "-in", "", parsed_args);
GetString(&out_path, "-out", "", parsed_args);
GetBoolArgument(&noout, "-noout", parsed_args);
GetBoolArgument(&modulus, "-modulus", parsed_args);

// Display rsa tool option summary
if (help) {
PrintUsage(kArguments);
return false;
}

// Check for required option -in
if (in_path.empty()) {
fprintf(stderr, "Error: missing required argument '-in'\n");
return false;
}

ScopedFILE in_file(fopen(in_path.c_str(), "rb"));
if (!in_file) {
fprintf(stderr, "Error: unable to load RSA key from '%s'\n", in_path.c_str());
return false;
}

bssl::UniquePtr<RSA> rsa(PEM_read_RSAPrivateKey(in_file.get(), nullptr, nullptr, nullptr));
if (!rsa) {
fprintf(stderr, "Error: unable to read RSA private key from '%s'\n", in_path.c_str());
return false;
}

ScopedFILE out_file;
if (!out_path.empty()) {
out_file.reset(fopen(out_path.c_str(), "wb"));
if (!out_file) {
fprintf(stderr, "Error: unable to open output file '%s'\n", out_path.c_str());
return false;
}
}

if (modulus) {
const BIGNUM *n = RSA_get0_n(rsa.get());
if (!n) {
fprintf(stderr, "Error: unable to load modulus\n");
return false;
}
char *hex_modulus = BN_bn2hex(n);
if (!hex_modulus) {
fprintf(stderr, "Error: unable to convert modulus to hex\n");
return false;
}
for (char *p = hex_modulus; *p; ++p) {
*p = toupper(*p);
}
if (out_file) {
fprintf(out_file.get(), "Modulus=%s\r\n", hex_modulus);
} else {
printf("Modulus=%s\n", hex_modulus);
}
OPENSSL_free(hex_modulus);
}

if (!noout) {
if (out_file) {
if (!PEM_write_RSAPrivateKey(out_file.get(), rsa.get(), nullptr, nullptr, 0, nullptr, nullptr)) {
fprintf(stderr, "Error: unable to write RSA private key to '%s'\n", out_path.c_str());
return false;
}
} else {
PEM_write_RSAPrivateKey(stdout, rsa.get(), nullptr, nullptr, 0, nullptr, nullptr);
}
}

return true;
}
Loading

0 comments on commit 5566a44

Please sign in to comment.