Skip to content

Commit 3dacb82

Browse files
committed
src: move EVP_CIPHER methods to ncrypto
1 parent e79a7aa commit 3dacb82

File tree

8 files changed

+259
-166
lines changed

8 files changed

+259
-166
lines changed

deps/ncrypto/ncrypto.cc

Lines changed: 135 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -312,23 +312,27 @@ BignumPointer BignumPointer::clone() {
312312
}
313313

314314
int BignumPointer::isPrime(int nchecks,
315-
BignumPointer::PrimeCheckCallback innerCb) const {
315+
BignumPointer::PrimeCheckCallback innerCb) const {
316316
BignumCtxPointer ctx(BN_CTX_new());
317317
BignumGenCallbackPointer cb(nullptr);
318318
if (innerCb != nullptr) {
319319
cb = BignumGenCallbackPointer(BN_GENCB_new());
320-
if (!cb) [[unlikely]] return -1;
321-
BN_GENCB_set(cb.get(), [](int a, int b, BN_GENCB* ctx) mutable -> int {
322-
PrimeCheckCallback& ptr =
323-
*static_cast<PrimeCheckCallback*>(BN_GENCB_get_arg(ctx));
324-
return ptr(a, b) ? 1 : 0;
325-
}, &innerCb);
320+
if (!cb) [[unlikely]]
321+
return -1;
322+
BN_GENCB_set(
323+
cb.get(),
324+
[](int a, int b, BN_GENCB* ctx) mutable -> int {
325+
PrimeCheckCallback& ptr =
326+
*static_cast<PrimeCheckCallback*>(BN_GENCB_get_arg(ctx));
327+
return ptr(a, b) ? 1 : 0;
328+
},
329+
&innerCb);
326330
}
327331
return BN_is_prime_ex(get(), nchecks, ctx.get(), cb.get());
328332
}
329333

330334
BignumPointer BignumPointer::NewPrime(const PrimeConfig& params,
331-
PrimeCheckCallback cb) {
335+
PrimeCheckCallback cb) {
332336
BignumPointer prime(BN_new());
333337
if (!prime || !prime.generate(params, std::move(cb))) {
334338
return {};
@@ -337,27 +341,30 @@ BignumPointer BignumPointer::NewPrime(const PrimeConfig& params,
337341
}
338342

339343
bool BignumPointer::generate(const PrimeConfig& params,
340-
PrimeCheckCallback innerCb) const {
344+
PrimeCheckCallback innerCb) const {
341345
// BN_generate_prime_ex() calls RAND_bytes_ex() internally.
342346
// Make sure the CSPRNG is properly seeded.
343347
CSPRNG(nullptr, 0);
344348
BignumGenCallbackPointer cb(nullptr);
345349
if (innerCb != nullptr) {
346350
cb = BignumGenCallbackPointer(BN_GENCB_new());
347-
if (!cb) [[unlikely]] return -1;
348-
BN_GENCB_set(cb.get(), [](int a, int b, BN_GENCB* ctx) mutable -> int {
349-
PrimeCheckCallback& ptr =
350-
*static_cast<PrimeCheckCallback*>(BN_GENCB_get_arg(ctx));
351-
return ptr(a, b) ? 1 : 0;
352-
}, &innerCb);
353-
}
354-
if (BN_generate_prime_ex(
355-
get(),
356-
params.bits,
357-
params.safe ? 1 : 0,
358-
params.add.get(),
359-
params.rem.get(),
360-
cb.get()) == 0) {
351+
if (!cb) [[unlikely]]
352+
return -1;
353+
BN_GENCB_set(
354+
cb.get(),
355+
[](int a, int b, BN_GENCB* ctx) mutable -> int {
356+
PrimeCheckCallback& ptr =
357+
*static_cast<PrimeCheckCallback*>(BN_GENCB_get_arg(ctx));
358+
return ptr(a, b) ? 1 : 0;
359+
},
360+
&innerCb);
361+
}
362+
if (BN_generate_prime_ex(get(),
363+
params.bits,
364+
params.safe ? 1 : 0,
365+
params.add.get(),
366+
params.rem.get(),
367+
cb.get()) == 0) {
361368
return false;
362369
}
363370

@@ -2228,13 +2235,11 @@ void SSLPointer::getCiphers(
22282235
// document them, but since there are only 5, easier to just add them manually
22292236
// and not have to explain their absence in the API docs. They are lower-cased
22302237
// because the docs say they will be.
2231-
static const char* TLS13_CIPHERS[] = {
2232-
"tls_aes_256_gcm_sha384",
2233-
"tls_chacha20_poly1305_sha256",
2234-
"tls_aes_128_gcm_sha256",
2235-
"tls_aes_128_ccm_8_sha256",
2236-
"tls_aes_128_ccm_sha256"
2237-
};
2238+
static const char* TLS13_CIPHERS[] = {"tls_aes_256_gcm_sha384",
2239+
"tls_chacha20_poly1305_sha256",
2240+
"tls_aes_128_gcm_sha256",
2241+
"tls_aes_128_ccm_8_sha256",
2242+
"tls_aes_128_ccm_sha256"};
22382243

22392244
const int n = sk_SSL_CIPHER_num(ciphers);
22402245

@@ -2259,7 +2264,7 @@ bool SSLPointer::setSniContext(const SSLCtxPointer& ctx) const {
22592264
auto x509 = ncrypto::X509View::From(ctx);
22602265
if (!x509) return false;
22612266
EVP_PKEY* pkey = SSL_CTX_get0_privatekey(ctx.get());
2262-
STACK_OF(X509)* chain;
2267+
STACK_OF(X509) * chain;
22632268

22642269
int err = SSL_CTX_get0_chain_certs(ctx.get(), &chain);
22652270
if (err == 1) err = SSL_use_certificate(get(), x509);
@@ -2281,7 +2286,7 @@ std::optional<uint32_t> SSLPointer::verifyPeerCertificate() const {
22812286
// looks like session resumption.
22822287
if (SSL_CIPHER_get_auth_nid(curr_cipher) == NID_auth_psk ||
22832288
(SSL_SESSION_get_protocol_version(sess) == TLS1_3_VERSION &&
2284-
SSL_session_reused(get()))) {
2289+
SSL_session_reused(get()))) {
22852290
return X509_V_OK;
22862291
}
22872292

@@ -2314,26 +2319,20 @@ const std::string_view SSLPointer::getClientHelloServerName() const {
23142319
size_t len;
23152320
size_t rem;
23162321

2317-
if (!SSL_client_hello_get0_ext(
2318-
get(),
2319-
TLSEXT_TYPE_server_name,
2320-
&buf,
2321-
&rem) || rem <= 2) {
2322+
if (!SSL_client_hello_get0_ext(get(), TLSEXT_TYPE_server_name, &buf, &rem) ||
2323+
rem <= 2) {
23222324
return nullptr;
23232325
}
23242326

23252327
len = (*buf << 8) | *(buf + 1);
2326-
if (len + 2 != rem)
2327-
return nullptr;
2328+
if (len + 2 != rem) return nullptr;
23282329
rem = len;
23292330

23302331
if (rem == 0 || *(buf + 2) != TLSEXT_NAMETYPE_host_name) return nullptr;
23312332
rem--;
2332-
if (rem <= 2)
2333-
return nullptr;
2333+
if (rem <= 2) return nullptr;
23342334
len = (*(buf + 3) << 8) | *(buf + 4);
2335-
if (len + 2 > rem)
2336-
return nullptr;
2335+
if (len + 2 > rem) return nullptr;
23372336
return reinterpret_cast<const char*>(buf + 5);
23382337
}
23392338

@@ -2383,7 +2382,9 @@ SSLCtxPointer& SSLCtxPointer::operator=(SSLCtxPointer&& other) noexcept {
23832382
return *new (this) SSLCtxPointer(std::move(other));
23842383
}
23852384

2386-
SSLCtxPointer::~SSLCtxPointer() { reset(); }
2385+
SSLCtxPointer::~SSLCtxPointer() {
2386+
reset();
2387+
}
23872388

23882389
void SSLCtxPointer::reset(SSL_CTX* ctx) {
23892390
ctx_.reset(ctx);
@@ -2413,4 +2414,94 @@ bool SSLCtxPointer::setGroups(const char* groups) {
24132414
return SSL_CTX_set1_groups_list(get(), groups) == 1;
24142415
}
24152416

2417+
// ============================================================================
2418+
2419+
const Cipher Cipher::FromName(const char* name) {
2420+
return Cipher(EVP_get_cipherbyname(name));
2421+
}
2422+
2423+
const Cipher Cipher::FromNid(int nid) {
2424+
return Cipher(EVP_get_cipherbynid(nid));
2425+
}
2426+
2427+
const Cipher Cipher::FromCtx(const CipherCtxPointer& ctx) {
2428+
return Cipher(EVP_CIPHER_CTX_cipher(ctx.get()));
2429+
}
2430+
2431+
int Cipher::getMode() const {
2432+
if (!cipher_) return 0;
2433+
return EVP_CIPHER_mode(cipher_);
2434+
}
2435+
2436+
int Cipher::getIvLength() const {
2437+
if (!cipher_) return 0;
2438+
return EVP_CIPHER_iv_length(cipher_);
2439+
}
2440+
2441+
int Cipher::getKeyLength() const {
2442+
if (!cipher_) return 0;
2443+
return EVP_CIPHER_key_length(cipher_);
2444+
}
2445+
2446+
int Cipher::getBlockSize() const {
2447+
if (!cipher_) return 0;
2448+
return EVP_CIPHER_block_size(cipher_);
2449+
}
2450+
2451+
int Cipher::getNid() const {
2452+
if (!cipher_) return 0;
2453+
return EVP_CIPHER_nid(cipher_);
2454+
}
2455+
2456+
const std::string_view Cipher::getModeLabel() const {
2457+
if (!cipher_) return {};
2458+
switch (getMode()) {
2459+
case EVP_CIPH_CCM_MODE:
2460+
return "ccm";
2461+
case EVP_CIPH_CFB_MODE:
2462+
return "cfb";
2463+
case EVP_CIPH_CBC_MODE:
2464+
return "cbc";
2465+
case EVP_CIPH_CTR_MODE:
2466+
return "ctr";
2467+
case EVP_CIPH_ECB_MODE:
2468+
return "ecb";
2469+
case EVP_CIPH_GCM_MODE:
2470+
return "gcm";
2471+
case EVP_CIPH_OCB_MODE:
2472+
return "ocb";
2473+
case EVP_CIPH_OFB_MODE:
2474+
return "ofb";
2475+
case EVP_CIPH_WRAP_MODE:
2476+
return "wrap";
2477+
case EVP_CIPH_XTS_MODE:
2478+
return "xts";
2479+
case EVP_CIPH_STREAM_CIPHER:
2480+
return "stream";
2481+
}
2482+
return "{unknown}";
2483+
}
2484+
2485+
const std::string_view Cipher::getName() const {
2486+
if (!cipher_) return {};
2487+
// OBJ_nid2sn(EVP_CIPHER_nid(cipher)) is used here instead of
2488+
// EVP_CIPHER_name(cipher) for compatibility with BoringSSL.
2489+
return OBJ_nid2sn(getNid());
2490+
}
2491+
2492+
bool Cipher::isSupportedAuthenticatedMode() const {
2493+
switch (getMode()) {
2494+
case EVP_CIPH_CCM_MODE:
2495+
case EVP_CIPH_GCM_MODE:
2496+
#ifndef OPENSSL_NO_OCB
2497+
case EVP_CIPH_OCB_MODE:
2498+
#endif
2499+
return true;
2500+
case EVP_CIPH_STREAM_CIPHER:
2501+
return getNid() == NID_chacha20_poly1305;
2502+
default:
2503+
return false;
2504+
}
2505+
}
2506+
24162507
} // namespace ncrypto

deps/ncrypto/ncrypto.h

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,40 @@ struct Buffer {
227227
size_t len = 0;
228228
};
229229

230+
class Cipher final {
231+
public:
232+
Cipher() = default;
233+
Cipher(const EVP_CIPHER* cipher) : cipher_(cipher) {}
234+
Cipher(const Cipher&) = default;
235+
Cipher& operator=(const Cipher&) = default;
236+
inline Cipher& operator=(const EVP_CIPHER* cipher) {
237+
cipher_ = cipher;
238+
return *this;
239+
}
240+
NCRYPTO_DISALLOW_MOVE(Cipher)
241+
242+
inline const EVP_CIPHER* get() const { return cipher_; }
243+
inline operator const EVP_CIPHER*() const { return cipher_; }
244+
inline operator bool() const { return cipher_ != nullptr; }
245+
246+
int getNid() const;
247+
int getMode() const;
248+
int getIvLength() const;
249+
int getKeyLength() const;
250+
int getBlockSize() const;
251+
const std::string_view getModeLabel() const;
252+
const std::string_view getName() const;
253+
254+
bool isSupportedAuthenticatedMode() const;
255+
256+
static const Cipher FromName(const char* name);
257+
static const Cipher FromNid(int nid);
258+
static const Cipher FromCtx(const CipherCtxPointer& ctx);
259+
260+
private:
261+
const EVP_CIPHER* cipher_ = nullptr;
262+
};
263+
230264
// A managed pointer to a buffer of data. When destroyed the underlying
231265
// buffer will be freed.
232266
class DataPointer final {
@@ -353,19 +387,20 @@ class BignumPointer final {
353387

354388
using PrimeCheckCallback = std::function<bool(int, int)>;
355389
int isPrime(int checks,
356-
PrimeCheckCallback cb = defaultPrimeCheckCallback) const;
390+
PrimeCheckCallback cb = defaultPrimeCheckCallback) const;
357391
struct PrimeConfig {
358392
int bits;
359393
bool safe = false;
360394
const BignumPointer& add;
361395
const BignumPointer& rem;
362396
};
363397

364-
static BignumPointer NewPrime(const PrimeConfig& params,
398+
static BignumPointer NewPrime(
399+
const PrimeConfig& params,
365400
PrimeCheckCallback cb = defaultPrimeCheckCallback);
366401

367402
bool generate(const PrimeConfig& params,
368-
PrimeCheckCallback cb = defaultPrimeCheckCallback) const;
403+
PrimeCheckCallback cb = defaultPrimeCheckCallback) const;
369404

370405
static BignumPointer New();
371406
static BignumPointer NewSecure();

src/crypto/crypto_aes.cc

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ WebCryptoCipherStatus AES_Cipher(Environment* env,
4040
ByteSource* out) {
4141
CHECK_EQ(key_data.GetKeyType(), kKeyTypeSecret);
4242

43-
const int mode = EVP_CIPHER_mode(params.cipher);
43+
const int mode = params.cipher.getMode();
4444

4545
CipherCtxPointer ctx(EVP_CIPHER_CTX_new());
4646
EVP_CIPHER_CTX_init(ctx.get());
@@ -478,13 +478,13 @@ Maybe<void> AESCipherTraits::AdditionalConfig(
478478
}
479479
#undef V
480480

481-
params->cipher = EVP_get_cipherbynid(cipher_nid);
482-
if (params->cipher == nullptr) {
481+
params->cipher = ncrypto::Cipher::FromNid(cipher_nid);
482+
if (!params->cipher) {
483483
THROW_ERR_CRYPTO_UNKNOWN_CIPHER(env);
484484
return Nothing<void>();
485485
}
486486

487-
int cipher_op_mode = EVP_CIPHER_mode(params->cipher);
487+
int cipher_op_mode = params->cipher.getMode();
488488
if (cipher_op_mode != EVP_CIPH_WRAP_MODE) {
489489
if (!ValidateIV(env, mode, args[offset + 1], params)) {
490490
return Nothing<void>();
@@ -503,8 +503,7 @@ Maybe<void> AESCipherTraits::AdditionalConfig(
503503
UseDefaultIV(params);
504504
}
505505

506-
if (params->iv.size() <
507-
static_cast<size_t>(EVP_CIPHER_iv_length(params->cipher))) {
506+
if (params->iv.size() < static_cast<size_t>(params->cipher.getIvLength())) {
508507
THROW_ERR_CRYPTO_INVALID_IV(env);
509508
return Nothing<void>();
510509
}

src/crypto/crypto_aes.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ enum AESKeyVariant {
3838
struct AESCipherConfig final : public MemoryRetainer {
3939
CryptoJobMode mode;
4040
AESKeyVariant variant;
41-
const EVP_CIPHER* cipher;
41+
ncrypto::Cipher cipher;
4242
size_t length;
4343
ByteSource iv; // Used for both iv or counter
4444
ByteSource additional_data;

0 commit comments

Comments
 (0)