Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ endif()
message(STATUS "CXX Namespace: ${SFRAME_CXX_NAMESPACE}")
message(STATUS "CMake Export Namespace: ${SFRAME_EXPORT_NAMESPACE}")

# Use -DCRYPTO=(OPENSSL_1_1 | OPENSSL_3 | BORINGSSL) to configure crypto
# Use -DCRYPTO=(OPENSSL_1_1 | OPENSSL_3 | BORINGSSL | STM32) to configure crypto
if(NOT DEFINED CRYPTO)
set(CRYPTO "OPENSSL_3")
endif()
Expand Down Expand Up @@ -92,8 +92,13 @@ elseif(${CRYPTO} STREQUAL "BORINGSSL")
find_package(OpenSSL REQUIRED)
add_compile_definitions(BORINGSSL)
set(CRYPTO_LIB OpenSSL::Crypto)
elseif(${CRYPTO} STREQUAL "STM32")
message(STATUS "Configuring with STM32")
find_package(STM32Cryptographic REQUIRED)
add_compile_definitions(STM32 NO_ALLOC)
set(CRYPTO_LIB STM32Cryptographic)
else()
message(FATAL_ERROR "Please select a crypto back-end (OPENSSL_1_1 or OPENSSL_3) [${CRYPTO}]")
message(FATAL_ERROR "Please select a crypto back-end (OPENSSL_1_1, OPENSSL_3, BORINGSSL, STM32) [${CRYPTO}]")
endif()


Expand Down
2 changes: 2 additions & 0 deletions include/sframe/sframe.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ namespace SFRAME_NAMESPACE {
struct crypto_error : std::runtime_error
{
crypto_error();
crypto_error(std::size_t err_code);
crypto_error(const std::string& err_str);
};

struct unsupported_ciphersuite_error : std::runtime_error
Expand Down
10 changes: 10 additions & 0 deletions src/crypto_boringssl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,16 @@ crypto_error::crypto_error()
{
}

crypto_error::crypto_error(std::size_t err_code)
: std::runtime_error(ERR_error_string(err_code, nullptr))
{
}

crypto_error::crypto_error(const std::string& err_str)
: std::runtime_error(err_str)
{
}

static const EVP_MD*
openssl_digest_type(CipherSuite suite)
{
Expand Down
10 changes: 10 additions & 0 deletions src/crypto_openssl11.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,16 @@ crypto_error::crypto_error()
{
}

crypto_error::crypto_error(std::size_t err_code)
: std::runtime_error(ERR_error_string(err_code, nullptr))
{
}

crypto_error::crypto_error(const std::string& err_str)
: std::runtime_error(err_str)
{
}

static const EVP_MD*
openssl_digest_type(CipherSuite suite)
{
Expand Down
10 changes: 10 additions & 0 deletions src/crypto_openssl3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,16 @@ crypto_error::crypto_error()
{
}

crypto_error::crypto_error(std::size_t err_code)
: std::runtime_error(ERR_error_string(err_code, nullptr))
{
}

crypto_error::crypto_error(const std::string& err_str)
: std::runtime_error(err_str)
{
}

static const EVP_CIPHER*
openssl_cipher(CipherSuite suite)
{
Expand Down
276 changes: 276 additions & 0 deletions src/crypto_stm32.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,276 @@
#if defined(STM32)

#include "crypto.h"
#include "header.h"

#include <cmox_crypto.h>
#include <cmox_init.h>
#include <cmox_low_level.h>
#include <mac/cmox_hmac.h>

#include <cstring>

namespace sframe {

#define VERIFY_CMOX_CALL(func, success_code) \
do { \
const auto retval = func; \
if (retval != success_code) { \
throw crypto_error(retval); \
} \
} while (0)

///
/// Convert between native identifiers / errors and cmox ones
///

crypto_error::crypto_error()
: std::runtime_error("unknown CMOX crypto error")
{
}

crypto_error::crypto_error(std::size_t err_code)
: std::runtime_error(
"CMOX crypto error (error_code=" + std::to_string(err_code) + ")")
{
}

crypto_error::crypto_error(const std::string& err_str)
: std::runtime_error("CMOX crypto error (error=" + err_str + ")")
{
}

static cmox_mac_algo_t
cmox_hmac_algo(CipherSuite suite)
{
switch (suite) {
case CipherSuite::AES_128_CTR_HMAC_SHA256_80:
case CipherSuite::AES_128_CTR_HMAC_SHA256_64:
case CipherSuite::AES_128_CTR_HMAC_SHA256_32:
case CipherSuite::AES_GCM_128_SHA256:
return CMOX_HMAC_SHA256_ALGO;
case CipherSuite::AES_GCM_256_SHA512:
return CMOX_HMAC_SHA512_ALGO;
default:
throw unsupported_ciphersuite_error();
}
}

static cmox_hmac_impl_t
cmox_hmac_impl(CipherSuite suite)
{
switch (suite) {
case CipherSuite::AES_128_CTR_HMAC_SHA256_80:
case CipherSuite::AES_128_CTR_HMAC_SHA256_64:
case CipherSuite::AES_128_CTR_HMAC_SHA256_32:
case CipherSuite::AES_GCM_128_SHA256:
return CMOX_HMAC_SHA256;
case CipherSuite::AES_GCM_256_SHA512:
return CMOX_HMAC_SHA512;
default:
throw unsupported_ciphersuite_error();
}
}

static std::size_t
cmox_hmac_size(CipherSuite suite)
{
switch (suite) {
case CipherSuite::AES_128_CTR_HMAC_SHA256_80:
case CipherSuite::AES_128_CTR_HMAC_SHA256_64:
case CipherSuite::AES_128_CTR_HMAC_SHA256_32:
case CipherSuite::AES_GCM_128_SHA256:
return CMOX_SHA256_SIZE;
case CipherSuite::AES_GCM_256_SHA512:
return CMOX_SHA512_SIZE;
default:
throw unsupported_ciphersuite_error();
}
}

///
/// HKDF
///

owned_bytes<max_hkdf_extract_size>
hkdf_extract(CipherSuite suite, input_bytes salt, input_bytes ikm)
{
std::size_t computed_size = 0;
const auto hmac_size = cmox_hmac_size(suite);
auto out = owned_bytes<max_hkdf_extract_size>(hmac_size);
VERIFY_CMOX_CALL(cmox_mac_compute(cmox_hmac_algo(suite),
ikm.data(),
ikm.size(),
salt.data(),
salt.size(),
nullptr,
0,
out.data(),
out.size(),
&computed_size),
CMOX_MAC_SUCCESS);

return out;
}

owned_bytes<max_hkdf_extract_size>
hkdf_expand(CipherSuite suite, input_bytes prk, input_bytes info, size_t size)
{
cmox_hmac_handle_t Hmac_Ctx;
cmox_mac_handle_t* mac_ctx;

const auto digest_size = cmox_hmac_size(suite);
auto N = static_cast<uint32_t>((size + digest_size - 1) / digest_size);

mac_ctx = cmox_hmac_construct(&Hmac_Ctx, cmox_hmac_impl(suite));
if (mac_ctx == nullptr) {
throw crypto_error();
}

owned_bytes<max_hkdf_extract_size> computed_hash(digest_size);
owned_bytes<max_hkdf_expand_size> out(size);

uint32_t index = 0;
for (uint8_t i = 1; i <= N; i++) {
computed_hash.resize(0);

VERIFY_CMOX_CALL(cmox_mac_init(mac_ctx), CMOX_MAC_SUCCESS);

VERIFY_CMOX_CALL(cmox_mac_setKey(mac_ctx, prk.data(), prk.size()),
CMOX_MAC_SUCCESS);

VERIFY_CMOX_CALL(cmox_mac_append(mac_ctx, info.data(), info.size()),
CMOX_MAC_SUCCESS);

VERIFY_CMOX_CALL(cmox_mac_append(mac_ctx, &i, 1), CMOX_MAC_SUCCESS);

computed_hash.resize(digest_size);
VERIFY_CMOX_CALL(
cmox_mac_generateTag(mac_ctx, computed_hash.data(), nullptr),
CMOX_MAC_SUCCESS);

const auto to_copy = (i == N) ? size - index : digest_size;
std::memcpy(&out[index], computed_hash.data(), to_copy);
index += to_copy;
}

VERIFY_CMOX_CALL(cmox_mac_cleanup(mac_ctx), CMOX_MAC_SUCCESS);

return out;
}

static output_bytes
seal_aead(CipherSuite suite,
input_bytes key,
input_bytes nonce,
output_bytes ct,
input_bytes aad,
input_bytes pt)
{
auto tag_size = cipher_overhead(suite);
if (ct.size() < pt.size() + tag_size) {
throw buffer_too_small_error("Ciphertext buffer too small");
}

std::size_t computed_size = 0;
VERIFY_CMOX_CALL(cmox_aead_encrypt(CMOX_AESFAST_GCMFAST_ENC_ALGO,
pt.data(),
pt.size(),
tag_size,
key.data(),
key.size(),
nonce.data(),
nonce.size(),
aad.data(),
aad.size(),
ct.data(),
&computed_size),
CMOX_CIPHER_SUCCESS);

return ct.subspan(0, computed_size);
}

output_bytes
seal(CipherSuite suite,
input_bytes key,
input_bytes nonce,
output_bytes ct,
input_bytes aad,
input_bytes pt)
{
switch (suite) {
case CipherSuite::AES_128_CTR_HMAC_SHA256_80:
case CipherSuite::AES_128_CTR_HMAC_SHA256_64:
case CipherSuite::AES_128_CTR_HMAC_SHA256_32: {
// TODO(GhostofCookie): return seal_ctr(suite, key, nonce, ct, aad, pt);
throw unsupported_ciphersuite_error();
}

case CipherSuite::AES_GCM_128_SHA256:
case CipherSuite::AES_GCM_256_SHA512: {
return seal_aead(suite, key, nonce, ct, aad, pt);
}
}

throw unsupported_ciphersuite_error();
}

static output_bytes
open_aead(CipherSuite suite,
input_bytes key,
input_bytes nonce,
output_bytes pt,
input_bytes aad,
input_bytes ct)
{
auto tag_size = cipher_overhead(suite);
if (ct.size() < tag_size) {
throw buffer_too_small_error("Ciphertext buffer too small");
}

std::size_t computed_size = 0;
VERIFY_CMOX_CALL(cmox_aead_decrypt(CMOX_AESFAST_GCMFAST_DEC_ALGO,
ct.data(),
ct.size(),
tag_size,
key.data(),
key.size(),
nonce.data(),
nonce.size(),
aad.data(),
aad.size(),
pt.data(),
&computed_size),
CMOX_CIPHER_AUTH_SUCCESS);

return pt.subspan(0, computed_size);
}

output_bytes
open(CipherSuite suite,
input_bytes key,
input_bytes nonce,
output_bytes pt,
input_bytes aad,
input_bytes ct)
{
switch (suite) {
case CipherSuite::AES_128_CTR_HMAC_SHA256_80:
case CipherSuite::AES_128_CTR_HMAC_SHA256_64:
case CipherSuite::AES_128_CTR_HMAC_SHA256_32: {
// TODO(GhostofCookie): return open_ctr(suite, key, nonce, pt, aad, ct);
throw unsupported_ciphersuite_error();
}

case CipherSuite::AES_GCM_128_SHA256:
case CipherSuite::AES_GCM_256_SHA512: {
return open_aead(suite, key, nonce, pt, aad, ct);
}
}

throw unsupported_ciphersuite_error();
}

} // namespace sframe

#endif
2 changes: 1 addition & 1 deletion src/sframe.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ KeyRecord::from_base_key(CipherSuite suite,
auto key_size = cipher_key_size(suite);
auto nonce_size = cipher_nonce_size(suite);

const auto empty_byte_string = owned_bytes<0>();
const auto empty_byte_string = owned_bytes<1>(0);
const auto key_label = sframe_key_label(suite, key_id);
const auto salt_label = sframe_salt_label(suite, key_id);

Expand Down
Loading