Skip to content

Commit 9dd1ec2

Browse files
committed
add lint
1 parent e406fb1 commit 9dd1ec2

10 files changed

Lines changed: 187 additions & 64 deletions

File tree

include/sframe/result.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,11 @@ class SFrameError
4848
const char* message_ = nullptr;
4949
};
5050

51+
#ifdef __cpp_exceptions
52+
void
53+
throw_sframe_error(const SFrameError& error);
54+
#endif
55+
5156
template<typename T>
5257
class Result
5358
{
@@ -92,6 +97,17 @@ class Result
9297

9398
bool is_err() const { return std::holds_alternative<SFrameError>(data_); }
9499

100+
#ifdef __cpp_exceptions
101+
T unwrap()
102+
{
103+
if (std::holds_alternative<SFrameError>(data_)) {
104+
throw_sframe_error(std::get<SFrameError>(data_));
105+
}
106+
107+
return std::move(std::get<T>(data_));
108+
}
109+
#endif
110+
95111
private:
96112
std::variant<T, SFrameError> data_;
97113
};
@@ -131,6 +147,15 @@ class Result<void>
131147

132148
bool is_err() const { return error_.has_value(); }
133149

150+
#ifdef __cpp_exceptions
151+
void unwrap()
152+
{
153+
if (error_.has_value()) {
154+
throw_sframe_error(error_.value());
155+
}
156+
}
157+
#endif
158+
134159
private:
135160
std::optional<SFrameError> error_;
136161
};

include/sframe/sframe.h

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88
#include <sframe/result.h>
99
#include <sframe/vector.h>
1010

11+
#ifdef __cpp_exceptions
12+
#include <stdexcept>
13+
#endif
14+
1115
#include <namespace.h>
1216

1317
// These constants define the size of certain internal data structures if
@@ -28,6 +32,41 @@
2832

2933
namespace SFRAME_NAMESPACE {
3034

35+
#ifdef __cpp_exceptions
36+
struct crypto_error : std::runtime_error
37+
{
38+
crypto_error();
39+
};
40+
41+
struct unsupported_ciphersuite_error : std::runtime_error
42+
{
43+
unsupported_ciphersuite_error();
44+
};
45+
46+
struct authentication_error : std::runtime_error
47+
{
48+
authentication_error();
49+
};
50+
51+
struct buffer_too_small_error : std::runtime_error
52+
{
53+
using parent = std::runtime_error;
54+
using parent::parent;
55+
};
56+
57+
struct invalid_parameter_error : std::runtime_error
58+
{
59+
using parent = std::runtime_error;
60+
using parent::parent;
61+
};
62+
63+
struct invalid_key_usage_error : std::runtime_error
64+
{
65+
using parent = std::runtime_error;
66+
using parent::parent;
67+
};
68+
#endif
69+
3170
enum class CipherSuite : uint16_t
3271
{
3372
AES_128_CTR_HMAC_SHA256_80 = 1,
@@ -140,16 +179,17 @@ class MLSContext : protected Context
140179
input_bytes metadata);
141180

142181
private:
182+
// NOLINTBEGIN(clang-analyzer-core.uninitialized.Assign)
143183
struct EpochKeys
144184
{
145185
static constexpr size_t max_secret_size = 64;
146186

147-
EpochID full_epoch = 0;
187+
EpochID full_epoch;
148188
owned_bytes<max_secret_size> sframe_epoch_secret;
149-
size_t sender_bits = 0;
150-
size_t context_bits = 0;
151-
uint64_t max_sender_id = 0;
152-
uint64_t max_context_id = 0;
189+
size_t sender_bits;
190+
size_t context_bits;
191+
uint64_t max_sender_id;
192+
uint64_t max_context_id;
153193

154194
EpochKeys() = default;
155195
static Result<EpochKeys> create(EpochID full_epoch_in,
@@ -159,6 +199,7 @@ class MLSContext : protected Context
159199
Result<owned_bytes<max_secret_size>> base_key(CipherSuite suite,
160200
SenderID sender_id) const;
161201
};
202+
// NOLINTEND(clang-analyzer-core.uninitialized.Assign)
162203

163204
void purge_epoch(EpochID epoch_id);
164205

src/crypto_boringssl.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ namespace SFRAME_NAMESPACE {
1717
/// Convert between native identifiers / errors and OpenSSL ones
1818
///
1919

20+
crypto_error::crypto_error()
21+
: std::runtime_error(ERR_error_string(ERR_get_error(), nullptr))
22+
{
23+
}
24+
2025
static Result<const EVP_MD*>
2126
openssl_digest_type(CipherSuite suite)
2227
{

src/crypto_openssl11.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ using scoped_hmac_ctx = std::unique_ptr<HMAC_CTX, decltype(&HMAC_CTX_free)>;
2323
/// Convert between native identifiers / errors and OpenSSL ones
2424
///
2525

26+
crypto_error::crypto_error()
27+
: std::runtime_error(ERR_error_string(ERR_get_error(), nullptr))
28+
{
29+
}
30+
2631
static Result<const EVP_MD*>
2732
openssl_digest_type(CipherSuite suite)
2833
{

src/crypto_openssl3.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ namespace SFRAME_NAMESPACE {
1717
/// Convert between native identifiers / errors and OpenSSL ones
1818
///
1919

20+
crypto_error::crypto_error()
21+
: std::runtime_error(ERR_error_string(ERR_get_error(), nullptr))
22+
{
23+
}
24+
2025
static Result<const EVP_CIPHER*>
2126
openssl_cipher(CipherSuite suite)
2227
{

src/result.cpp

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,39 @@
1-
#include <sframe/result.h>
1+
#include <sframe/sframe.h>
2+
3+
namespace SFRAME_NAMESPACE {
4+
5+
#ifdef __cpp_exceptions
6+
unsupported_ciphersuite_error::unsupported_ciphersuite_error()
7+
: std::runtime_error("Unsupported ciphersuite")
8+
{
9+
}
10+
11+
authentication_error::authentication_error()
12+
: std::runtime_error("AEAD authentication failure")
13+
{
14+
}
15+
16+
[[noreturn]] void
17+
throw_sframe_error(const SFrameError& error)
18+
{
19+
switch (error.type()) {
20+
case SFrameErrorType::internal_error:
21+
throw std::runtime_error(error.message() ? error.message()
22+
: "SFrame internal error");
23+
case SFrameErrorType::buffer_too_small_error:
24+
throw buffer_too_small_error(error.message());
25+
case SFrameErrorType::invalid_parameter_error:
26+
throw invalid_parameter_error(error.message());
27+
case SFrameErrorType::crypto_error:
28+
throw crypto_error();
29+
case SFrameErrorType::unsupported_ciphersuite_error:
30+
throw unsupported_ciphersuite_error();
31+
case SFrameErrorType::authentication_error:
32+
throw authentication_error();
33+
case SFrameErrorType::invalid_key_usage_error:
34+
throw invalid_key_usage_error(error.message());
35+
}
36+
}
37+
#endif
38+
39+
} // namespace SFRAME_NAMESPACE

test/common.h

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,9 @@
22
#include <sframe/result.h>
33
#include <sframe/sframe.h>
44

5-
#include <stdexcept>
65
#include <string>
76
#include <vector>
87

9-
// Unwrap a Result<T> in a test context. Throws std::runtime_error on error
10-
// so doctest can catch and report it.
11-
#define UNWRAP(expr) \
12-
([&]() { \
13-
auto _r = (expr); \
14-
if (_r.is_err()) { \
15-
const auto* _msg = _r.error().message(); \
16-
throw std::runtime_error(_msg ? _msg : "unwrap() on an error result"); \
17-
} \
18-
return _r.value(); \
19-
}())
20-
218
using bytes = std::vector<uint8_t>;
229

2310
bytes

test/header.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ TEST_CASE("Header Known-Answer")
3838

3939
for (const auto& tc : cases) {
4040
// Decode
41-
const auto decoded = UNWRAP(Header::parse(tc.encoding));
41+
const auto decoded = Header::parse(tc.encoding).unwrap();
4242
REQUIRE(decoded.key_id == tc.key_id);
4343
REQUIRE(decoded.counter == tc.counter);
4444
REQUIRE(decoded.size() == tc.encoding.size());

test/sframe.cpp

Lines changed: 53 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,15 @@ TEST_CASE("SFrame Round-Trip")
3939
auto& key = pair.second;
4040

4141
auto send = Context(suite);
42-
UNWRAP(send.add_key(kid, KeyUsage::protect, key));
42+
send.add_key(kid, KeyUsage::protect, key).unwrap();
4343

4444
auto recv = Context(suite);
45-
UNWRAP(recv.add_key(kid, KeyUsage::unprotect, key));
45+
recv.add_key(kid, KeyUsage::unprotect, key).unwrap();
4646

4747
for (int i = 0; i < rounds; i++) {
4848
auto encrypted =
49-
to_bytes(UNWRAP(send.protect(kid, ct_out, plaintext, {})));
50-
auto decrypted = to_bytes(UNWRAP(recv.unprotect(pt_out, encrypted, {})));
49+
to_bytes(send.protect(kid, ct_out, plaintext, {}).unwrap());
50+
auto decrypted = to_bytes(recv.unprotect(pt_out, encrypted, {}).unwrap());
5151
CHECK(decrypted == plaintext);
5252
}
5353
}
@@ -82,20 +82,22 @@ TEST_CASE("MLS Round-Trip")
8282
for (MLSContext::EpochID epoch_id = 0; epoch_id < test_epochs; epoch_id++) {
8383
const auto sframe_epoch_secret = bytes(8, uint8_t(epoch_id));
8484

85-
UNWRAP(member_a.add_epoch(epoch_id, sframe_epoch_secret));
86-
UNWRAP(member_b.add_epoch(epoch_id, sframe_epoch_secret));
85+
member_a.add_epoch(epoch_id, sframe_epoch_secret).unwrap();
86+
member_b.add_epoch(epoch_id, sframe_epoch_secret).unwrap();
8787

8888
for (int i = 0; i < epoch_rounds; i++) {
89-
auto encrypted_ab = UNWRAP(
90-
member_a.protect(epoch_id, sender_id_a, ct_out, plaintext, metadata));
89+
auto encrypted_ab =
90+
member_a.protect(epoch_id, sender_id_a, ct_out, plaintext, metadata)
91+
.unwrap();
9192
auto decrypted_ab =
92-
UNWRAP(member_b.unprotect(pt_out, encrypted_ab, metadata));
93+
member_b.unprotect(pt_out, encrypted_ab, metadata).unwrap();
9394
CHECK(plaintext == to_bytes(decrypted_ab));
9495

95-
auto encrypted_ba = UNWRAP(
96-
member_b.protect(epoch_id, sender_id_b, ct_out, plaintext, metadata));
96+
auto encrypted_ba =
97+
member_b.protect(epoch_id, sender_id_b, ct_out, plaintext, metadata)
98+
.unwrap();
9799
auto decrypted_ba =
98-
UNWRAP(member_a.unprotect(pt_out, encrypted_ba, metadata));
100+
member_a.unprotect(pt_out, encrypted_ba, metadata).unwrap();
99101
CHECK(plaintext == to_bytes(decrypted_ba));
100102
}
101103
}
@@ -135,33 +137,46 @@ TEST_CASE("MLS Round-Trip with context")
135137
for (MLSContext::EpochID epoch_id = 0; epoch_id < test_epochs; epoch_id++) {
136138
const auto sframe_epoch_secret = bytes(8, uint8_t(epoch_id));
137139

138-
UNWRAP(
139-
member_a_0.add_epoch(epoch_id, sframe_epoch_secret, sender_id_bits));
140-
UNWRAP(
141-
member_a_1.add_epoch(epoch_id, sframe_epoch_secret, sender_id_bits));
142-
UNWRAP(member_b.add_epoch(epoch_id, sframe_epoch_secret));
140+
member_a_0.add_epoch(epoch_id, sframe_epoch_secret, sender_id_bits)
141+
.unwrap();
142+
member_a_1.add_epoch(epoch_id, sframe_epoch_secret, sender_id_bits)
143+
.unwrap();
144+
member_b.add_epoch(epoch_id, sframe_epoch_secret).unwrap();
143145

144146
for (int i = 0; i < epoch_rounds; i++) {
145-
auto encrypted_ab_0 = UNWRAP(member_a_0.protect(
146-
epoch_id, sender_id_a, context_id_0, ct_out_0, plaintext, metadata));
147+
auto encrypted_ab_0 = member_a_0
148+
.protect(epoch_id,
149+
sender_id_a,
150+
context_id_0,
151+
ct_out_0,
152+
plaintext,
153+
metadata)
154+
.unwrap();
147155
auto decrypted_ab_0 = to_bytes(
148-
UNWRAP(member_b.unprotect(pt_out, encrypted_ab_0, metadata)));
156+
member_b.unprotect(pt_out, encrypted_ab_0, metadata).unwrap());
149157
CHECK(plaintext == decrypted_ab_0);
150158

151-
auto encrypted_ab_1 = UNWRAP(member_a_1.protect(
152-
epoch_id, sender_id_a, context_id_1, ct_out_1, plaintext, metadata));
159+
auto encrypted_ab_1 = member_a_1
160+
.protect(epoch_id,
161+
sender_id_a,
162+
context_id_1,
163+
ct_out_1,
164+
plaintext,
165+
metadata)
166+
.unwrap();
153167
auto decrypted_ab_1 = to_bytes(
154-
UNWRAP(member_b.unprotect(pt_out, encrypted_ab_1, metadata)));
168+
member_b.unprotect(pt_out, encrypted_ab_1, metadata).unwrap());
155169
CHECK(plaintext == decrypted_ab_1);
156170

157171
CHECK(to_bytes(encrypted_ab_0) != to_bytes(encrypted_ab_1));
158172

159-
auto encrypted_ba = UNWRAP(member_b.protect(
160-
epoch_id, sender_id_b, ct_out_0, plaintext, metadata));
173+
auto encrypted_ba =
174+
member_b.protect(epoch_id, sender_id_b, ct_out_0, plaintext, metadata)
175+
.unwrap();
161176
auto decrypted_ba_0 = to_bytes(
162-
UNWRAP(member_a_0.unprotect(pt_out, encrypted_ba, metadata)));
177+
member_a_0.unprotect(pt_out, encrypted_ba, metadata).unwrap());
163178
auto decrypted_ba_1 = to_bytes(
164-
UNWRAP(member_a_1.unprotect(pt_out, encrypted_ba, metadata)));
179+
member_a_1.unprotect(pt_out, encrypted_ba, metadata).unwrap());
165180
CHECK(plaintext == decrypted_ba_0);
166181
CHECK(plaintext == decrypted_ba_1);
167182
}
@@ -187,17 +202,18 @@ TEST_CASE("MLS Failure after Purge")
187202

188203
// Install epoch 1 and create a cipihertext
189204
const auto epoch_id_1 = MLSContext::EpochID(1);
190-
UNWRAP(member_a.add_epoch(epoch_id_1, sframe_epoch_secret_1));
191-
UNWRAP(member_b.add_epoch(epoch_id_1, sframe_epoch_secret_1));
205+
member_a.add_epoch(epoch_id_1, sframe_epoch_secret_1).unwrap();
206+
member_b.add_epoch(epoch_id_1, sframe_epoch_secret_1).unwrap();
192207

193-
const auto enc_ab_1 = UNWRAP(
194-
member_a.protect(epoch_id_1, sender_id_a, ct_out, plaintext, metadata));
208+
const auto enc_ab_1 =
209+
member_a.protect(epoch_id_1, sender_id_a, ct_out, plaintext, metadata)
210+
.unwrap();
195211
const auto enc_ab_1_data = to_bytes(enc_ab_1);
196212

197213
// Install epoch 2
198214
const auto epoch_id_2 = MLSContext::EpochID(2);
199-
UNWRAP(member_a.add_epoch(epoch_id_2, sframe_epoch_secret_2));
200-
UNWRAP(member_b.add_epoch(epoch_id_2, sframe_epoch_secret_2));
215+
member_a.add_epoch(epoch_id_2, sframe_epoch_secret_2).unwrap();
216+
member_b.add_epoch(epoch_id_2, sframe_epoch_secret_2).unwrap();
201217

202218
// Purge epoch 1 and verify failure
203219
member_a.purge_before(epoch_id_2);
@@ -209,8 +225,9 @@ TEST_CASE("MLS Failure after Purge")
209225
CHECK(member_b.unprotect(pt_out, enc_ab_1_data, metadata).error().type() ==
210226
SFrameErrorType::invalid_parameter_error);
211227

212-
const auto enc_ab_2 = UNWRAP(
213-
member_a.protect(epoch_id_2, sender_id_a, ct_out, plaintext, metadata));
214-
const auto dec_ab_2 = UNWRAP(member_b.unprotect(pt_out, enc_ab_2, metadata));
228+
const auto enc_ab_2 =
229+
member_a.protect(epoch_id_2, sender_id_a, ct_out, plaintext, metadata)
230+
.unwrap();
231+
const auto dec_ab_2 = member_b.unprotect(pt_out, enc_ab_2, metadata).unwrap();
215232
CHECK(plaintext == to_bytes(dec_ab_2));
216233
}

0 commit comments

Comments
 (0)