-
Notifications
You must be signed in to change notification settings - Fork 121
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Description: - Developed structure for new OpenSSL tools - Contains initial implementation for OpenSSL x509 tool, options -in and -out (x509.cc), and unit test (x509_test.cc) - x509_test.cc contains test portions ultimately to be used for future options but unnecessary for -in/-out unit test _Files expected to change_ By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license and the ISC license.
- Loading branch information
Showing
8 changed files
with
382 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
add_executable( | ||
openssl | ||
|
||
../tool/args.cc | ||
../tool/file.cc | ||
tool.cc | ||
x509.cc | ||
) | ||
|
||
target_include_directories(openssl PUBLIC ${PROJECT_SOURCE_DIR}/include) | ||
target_compile_options(openssl PUBLIC -DINTERNAL_TOOL) | ||
|
||
if(WIN32) | ||
target_link_libraries(openssl ws2_32) | ||
endif() | ||
|
||
if(APPLE OR WIN32 OR ANDROID) | ||
target_link_libraries(openssl ssl crypto) | ||
set(LIBRT_FLAG "") | ||
else() | ||
find_library(FOUND_LIBRT rt) | ||
if(FOUND_LIBRT) | ||
target_link_libraries(openssl ssl crypto -lrt) | ||
set(LIBRT_FLAG "-lrt") | ||
else() | ||
target_link_libraries(openssl ssl crypto) | ||
set(LIBRT_FLAG "") | ||
endif() | ||
endif() | ||
|
||
target_include_directories(openssl BEFORE PRIVATE ${PROJECT_BINARY_DIR}/symbol_prefix_include) | ||
|
||
install(TARGETS openssl | ||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} | ||
BUNDLE DESTINATION ${CMAKE_INSTALL_BINDIR} | ||
) | ||
|
||
if(MSVC AND CMAKE_BUILD_TYPE_LOWER MATCHES "relwithdebinfo" AND FIPS) | ||
install (FILES $<TARGET_FILE_DIR:openssl>/openssl.pdb DESTINATION ${CMAKE_INSTALL_LIBDIR}) | ||
endif() | ||
|
||
if(BUILD_TESTING) | ||
add_executable( | ||
tool_openssl_test | ||
|
||
x509_test.cc | ||
../tool/args.cc | ||
../tool/file.cc | ||
x509.cc | ||
) | ||
|
||
target_link_libraries(tool_openssl_test boringssl_gtest_main ssl crypto) | ||
target_include_directories(tool_openssl_test BEFORE PRIVATE ${PROJECT_BINARY_DIR}/symbol_prefix_include) | ||
add_dependencies(all_tests tool_openssl_test) | ||
endif() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
# OpenSSL Tools for AWS-LC | ||
*Files expected to change* | ||
|
||
Current status: | ||
* Developed structure for new OpenSSL tools | ||
* Contains initial implementation for OpenSSL x509 tool, options -in and -out (x509.cc), and unit test (x509_test.cc) | ||
* x509_test.cc contains test portions ultimately to be used for future options but unnecessary for -in/-out unit test | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
// SPDX-License-Identifier: Apache-2.0 OR ISC | ||
|
||
#ifndef INTERNAL_H | ||
#define INTERNAL_H | ||
|
||
#include "../tool/internal.h" | ||
#include <string> | ||
#include <vector> | ||
|
||
typedef bool (*tool_func_t)(const std::vector<std::string> &args); | ||
|
||
X509* CreateAndSignX509Certificate(); | ||
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); | ||
|
||
#endif //INTERNAL_H | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
// SPDX-License-Identifier: Apache-2.0 OR ISC | ||
|
||
#include <array> | ||
#include <iostream> | ||
#include <openssl/ssl.h> | ||
|
||
#if defined(OPENSSL_WINDOWS) | ||
#include <fcntl.h> | ||
#include <io.h> | ||
#else | ||
#include <libgen.h> | ||
#include <signal.h> | ||
#endif | ||
|
||
#include "./internal.h" | ||
|
||
typedef bool (*tool_func_t)(const std::vector<std::string> &args); | ||
|
||
struct Tool { | ||
const char *name; | ||
tool_func_t func; | ||
}; | ||
|
||
static const std::array<Tool, 1> kTools = {{ | ||
{ "x509", X509Tool }, | ||
}}; | ||
|
||
static void usage(const std::string &name) { | ||
std::cout << "Usage: " << name << " COMMAND\n\n"; | ||
std::cout << "Available commands:\n"; | ||
|
||
for (const auto& tool : kTools) { | ||
if (tool.func == nullptr) { | ||
break; | ||
} | ||
std::cout << " " << tool.name << "\n"; | ||
} | ||
} | ||
|
||
static void initialize() { | ||
#if defined(OPENSSL_WINDOWS) | ||
// Read and write in binary mode. This makes bssl on Windows consistent with | ||
// bssl on other platforms, and also makes it consistent with MSYS's commands | ||
// like diff(1) and md5sum(1). This is especially important for the digest | ||
// commands. | ||
if (_setmode(_fileno(stdin), _O_BINARY) == -1) { | ||
perror("_setmode(_fileno(stdin), O_BINARY)"); | ||
exit(1); | ||
} | ||
if (_setmode(_fileno(stdout), _O_BINARY) == -1) { | ||
perror("_setmode(_fileno(stdout), O_BINARY)"); | ||
exit(1); | ||
} | ||
if (_setmode(_fileno(stderr), _O_BINARY) == -1) { | ||
perror("_setmode(_fileno(stderr), O_BINARY)"); | ||
exit(1); | ||
} | ||
#else | ||
// Ignore SIGPIPE to prevent the process from terminating if it tries to | ||
// write to a pipe that has been closed by the reading end. SIGPIPE can be | ||
// received when writing to sockets or pipes that are no longer connected. | ||
signal(SIGPIPE, SIG_IGN); | ||
#endif | ||
} | ||
|
||
tool_func_t FindTool(const std::string &name) { | ||
for (const auto& tool : kTools) { | ||
if (tool.name == name) { | ||
return tool.func; | ||
} | ||
} | ||
return nullptr; | ||
} | ||
|
||
tool_func_t FindTool(int argc, char **argv, int &starting_arg) { | ||
#if !defined(OPENSSL_WINDOWS) | ||
tool_func_t tool = FindTool(basename(argv[0])); | ||
if (tool != nullptr) { | ||
return tool; | ||
} | ||
#endif | ||
starting_arg++; | ||
if (argc > 1) { | ||
return FindTool(argv[1]); | ||
} | ||
return nullptr; | ||
} | ||
|
||
int main(int argc, char **argv) { | ||
initialize(); | ||
CRYPTO_library_init(); | ||
|
||
int starting_arg = 1; | ||
tool_func_t tool = FindTool(argc, argv, starting_arg); | ||
|
||
if (tool == nullptr) { | ||
usage(argv[0]); | ||
return 1; | ||
} | ||
|
||
args_list_t args; | ||
for (int i = starting_arg; i < argc; i++) { | ||
args.emplace_back(argv[i]); | ||
} | ||
|
||
if (!tool(args)) { | ||
ERR_print_errors_fp(stderr); | ||
return 1; | ||
} | ||
|
||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
// SPDX-License-Identifier: Apache-2.0 OR ISC | ||
|
||
#include <openssl/x509.h> | ||
#include <openssl/pem.h> | ||
#include "internal.h" | ||
|
||
static const argument_t kArguments[] = { | ||
{ "-in", kRequiredArgument, "Input file" }, | ||
{ "-out", kRequiredArgument, "Output file" }, | ||
{ "", kOptionalArgument, "" } | ||
}; | ||
|
||
// Map arguments using tool/args.cc | ||
bool X509Tool(const args_list_t &args) { | ||
args_map_t parsed_args; | ||
if (!ParseKeyValueArguments(&parsed_args, args, kArguments)) { | ||
PrintUsage(kArguments); | ||
return false; | ||
} | ||
|
||
// Check for required arguments | ||
std::string in_path, out_path; | ||
if (!GetString(&in_path, "-in", "", parsed_args)) { | ||
fprintf(stderr, "Missing required argument: -in\n"); | ||
PrintUsage(kArguments); | ||
return false; | ||
} | ||
if (!GetString(&out_path, "-out", "", parsed_args)) { | ||
fprintf(stderr, "Missing required argument: -out\n"); | ||
PrintUsage(kArguments); | ||
return false; | ||
} | ||
|
||
// Read input file using ReadAll function from tool/file.cc | ||
std::vector<uint8_t> input_data; | ||
ScopedFILE in_file(fopen(in_path.c_str(), "rb")); | ||
if (!in_file) { | ||
fprintf(stderr, "Failed to open input file '%s'.\n", in_path.c_str()); | ||
return false; | ||
} | ||
if (!ReadAll(&input_data, in_file.get())) { | ||
fprintf(stderr, "Failed to read input file '%s'.\n", in_path.c_str()); | ||
return false; | ||
} | ||
|
||
// Parse x509 certificate from input file | ||
const uint8_t *p = input_data.data(); | ||
bssl::UniquePtr<X509> x509(d2i_X509(nullptr, &p, input_data.size())); | ||
if (!x509) { | ||
fprintf(stderr, "Failed to parse X509 certificate from '%s'.\n", in_path.c_str()); | ||
ERR_print_errors_fp(stderr); | ||
return false; | ||
} | ||
|
||
// Serialize certificate to DER format | ||
uint8_t *out_data = nullptr; | ||
int len = i2d_X509(x509.get(), &out_data); | ||
if (len < 0) { | ||
fprintf(stderr, "Failed to serialize X509 certificate.\n"); | ||
ERR_print_errors_fp(stderr); | ||
return false; | ||
} | ||
|
||
// Write output file using WriteToFile function from tool/file.cc | ||
if (!WriteToFile(out_path, out_data, len)) { | ||
fprintf(stderr, "Failed to write X509 certificate to '%s'.\n", out_path.c_str()); | ||
OPENSSL_free(out_data); | ||
return false; | ||
} | ||
|
||
OPENSSL_free(out_data); | ||
return true; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
// SPDX-License-Identifier: Apache-2.0 OR ISC | ||
|
||
#include "openssl/x509.h" | ||
#include <openssl/err.h> | ||
#include <gtest/gtest.h> | ||
#include "../tool/internal.h" | ||
#include "internal.h" | ||
|
||
#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]); | ||
|
||
X509* CreateAndSignX509Certificate() { | ||
bssl::UniquePtr<X509> x509(X509_new()); | ||
if (!x509) return nullptr; | ||
|
||
// Set validity period for 1 year | ||
if (!X509_gmtime_adj(X509_getm_notBefore(x509.get()), 0) || | ||
!X509_gmtime_adj(X509_getm_notAfter(x509.get()), 31536000L)) { | ||
return nullptr; | ||
} | ||
|
||
// Generate and set the public key | ||
bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new()); | ||
if (!pkey) { | ||
return nullptr; | ||
} | ||
bssl::UniquePtr<RSA> rsa(RSA_new()); | ||
bssl::UniquePtr<BIGNUM> bn(BN_new()); | ||
if (!bn || !BN_set_word(bn.get(), RSA_F4) || | ||
!RSA_generate_key_ex(rsa.get(), 2048, bn.get(), nullptr) || | ||
!EVP_PKEY_assign_RSA(pkey.get(), rsa.release())) { | ||
return nullptr; | ||
} | ||
if (!X509_set_pubkey(x509.get(), pkey.get())) { | ||
return nullptr; | ||
} | ||
|
||
// Sign certificate | ||
if (X509_sign(x509.get(), pkey.get(), EVP_sha256()) <= 0) { | ||
return nullptr; | ||
} | ||
|
||
return x509.release(); | ||
} | ||
|
||
// Test x509 -in and -out | ||
TEST(X509Test, X509ToolTest) { | ||
char in_path[PATH_MAX]; | ||
char out_path[PATH_MAX]; | ||
|
||
ASSERT_GT(createTempFILEpath(in_path), 0u); | ||
ASSERT_GT(createTempFILEpath(out_path), 0u); | ||
|
||
bssl::UniquePtr<X509> x509(CreateAndSignX509Certificate()); | ||
ASSERT_TRUE(x509); | ||
|
||
// Serialize certificate to DER format | ||
uint8_t *der_data = nullptr; | ||
int len = i2d_X509(x509.get(), &der_data); | ||
ASSERT_GT(static_cast<size_t>(len), 0u); | ||
|
||
ScopedFILE in_file(fopen(in_path, "wb")); | ||
ASSERT_TRUE(in_file); | ||
fwrite(der_data, 1, len, in_file.get()); | ||
OPENSSL_free(der_data); | ||
|
||
in_file.reset(); | ||
|
||
// Set up x509 tool arguments | ||
args_list_t args = {"-in", in_path, "-out", out_path}; | ||
|
||
// Call x509 tool function | ||
bool result = X509Tool(args); | ||
ASSERT_TRUE(result); | ||
|
||
// Read and verify output file | ||
ScopedFILE out_file(fopen(out_path, "rb")); | ||
ASSERT_TRUE(out_file); | ||
|
||
std::vector<uint8_t> output_data; | ||
ASSERT_TRUE(ReadAll(&output_data, out_file.get())); | ||
|
||
// Ensure output data not empty | ||
ASSERT_FALSE(output_data.empty()); | ||
|
||
// Parse x509 cert from output file | ||
const uint8_t *p = output_data.data(); | ||
bssl::UniquePtr<X509> parsed_x509(d2i_X509(nullptr, &p, output_data.size())); | ||
ASSERT_TRUE(parsed_x509); | ||
|
||
remove(in_path); | ||
remove(out_path); | ||
} |
Oops, something went wrong.