Skip to content

Commit

Permalink
Merge pull request #3108 from cloudflare/jsnell/node-crypto-dh-use-bu…
Browse files Browse the repository at this point in the history
…ffersource
  • Loading branch information
jasnell authored Nov 13, 2024
2 parents 158d137 + fef9432 commit 159766b
Show file tree
Hide file tree
Showing 8 changed files with 80 additions and 46 deletions.
32 changes: 16 additions & 16 deletions src/workerd/api/crypto/dh.c++
Original file line number Diff line number Diff line change
Expand Up @@ -217,31 +217,31 @@ void DiffieHellman::setPublicKey(kj::ArrayPtr<kj::byte> key) {
OSSLCALL(DH_set0_key(dh, toBignumUnowned(key), nullptr));
}

kj::Array<kj::byte> DiffieHellman::getPublicKey() {
jsg::BufferSource DiffieHellman::getPublicKey(jsg::Lock& js) {
const BIGNUM* pub_key = DH_get0_pub_key(dh);
return JSG_REQUIRE_NONNULL(
bignumToArrayPadded(*pub_key), Error, "Error while retrieving DiffieHellman public key");
bignumToArrayPadded(js, *pub_key), Error, "Error while retrieving DiffieHellman public key");
}

kj::Array<kj::byte> DiffieHellman::getPrivateKey() {
jsg::BufferSource DiffieHellman::getPrivateKey(jsg::Lock& js) {
const BIGNUM* priv_key = DH_get0_priv_key(dh);
return JSG_REQUIRE_NONNULL(
bignumToArrayPadded(*priv_key), Error, "Error while retrieving DiffieHellman private key");
return JSG_REQUIRE_NONNULL(bignumToArrayPadded(js, *priv_key), Error,
"Error while retrieving DiffieHellman private key");
}

kj::Array<kj::byte> DiffieHellman::getGenerator() {
jsg::BufferSource DiffieHellman::getGenerator(jsg::Lock& js) {
const BIGNUM* g = DH_get0_g(dh);
return JSG_REQUIRE_NONNULL(
bignumToArrayPadded(*g), Error, "Error while retrieving DiffieHellman generator");
bignumToArrayPadded(js, *g), Error, "Error while retrieving DiffieHellman generator");
}

kj::Array<kj::byte> DiffieHellman::getPrime() {
jsg::BufferSource DiffieHellman::getPrime(jsg::Lock& js) {
const BIGNUM* p = DH_get0_p(dh);
return JSG_REQUIRE_NONNULL(
bignumToArrayPadded(*p), Error, "Error while retrieving DiffieHellman prime");
bignumToArrayPadded(js, *p), Error, "Error while retrieving DiffieHellman prime");
}

kj::Array<kj::byte> DiffieHellman::computeSecret(kj::ArrayPtr<kj::byte> key) {
jsg::BufferSource DiffieHellman::computeSecret(jsg::Lock& js, kj::ArrayPtr<kj::byte> key) {
JSG_REQUIRE(key.size() <= INT32_MAX, RangeError,
"DiffieHellman computeSecret() failed: key is too large");
JSG_REQUIRE(key.size() > 0, Error, "DiffieHellman computeSecret() failed: invalid key");
Expand All @@ -251,9 +251,9 @@ kj::Array<kj::byte> DiffieHellman::computeSecret(kj::ArrayPtr<kj::byte> key) {
toBignum(key), Error, "Error getting key while computing DiffieHellman secret");

size_t prime_size = DH_size(dh);
auto prime_enc = kj::heapArray<kj::byte>(prime_size);
auto prime_enc = jsg::BackingStore::alloc<v8::ArrayBuffer>(js, prime_size);

int size = DH_compute_key(prime_enc.begin(), k.get(), dh);
int size = DH_compute_key(prime_enc.asArrayPtr().begin(), k.get(), dh);
if (size == -1) {
// various error checking
int checkResult;
Expand All @@ -269,16 +269,16 @@ kj::Array<kj::byte> DiffieHellman::computeSecret(kj::ArrayPtr<kj::byte> key) {
}

KJ_ASSERT(size >= 0);
zeroPadDiffieHellmanSecret(size, prime_enc.begin(), prime_size);
return prime_enc;
zeroPadDiffieHellmanSecret(size, prime_enc.asArrayPtr().begin(), prime_size);
return jsg::BufferSource(js, kj::mv(prime_enc));
}

kj::Array<kj::byte> DiffieHellman::generateKeys() {
jsg::BufferSource DiffieHellman::generateKeys(jsg::Lock& js) {
ClearErrorOnReturn clear_error_on_return;
OSSLCALL(DH_generate_key(dh));
const BIGNUM* pub_key = DH_get0_pub_key(dh);
return JSG_REQUIRE_NONNULL(
bignumToArrayPadded(*pub_key), Error, "Error while generating DiffieHellman keys");
bignumToArrayPadded(js, *pub_key), Error, "Error while generating DiffieHellman keys");
}

} // namespace workerd::api
14 changes: 8 additions & 6 deletions src/workerd/api/crypto/dh.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

#include "impl.h"

#include <workerd/jsg/jsg.h>

#include <openssl/dh.h>

#include <kj/common.h>
Expand All @@ -20,12 +22,12 @@ class DiffieHellman final {
void setPrivateKey(kj::ArrayPtr<kj::byte> key);
void setPublicKey(kj::ArrayPtr<kj::byte> key);

kj::Array<kj::byte> getPublicKey() KJ_WARN_UNUSED_RESULT;
kj::Array<kj::byte> getPrivateKey() KJ_WARN_UNUSED_RESULT;
kj::Array<kj::byte> getGenerator() KJ_WARN_UNUSED_RESULT;
kj::Array<kj::byte> getPrime() KJ_WARN_UNUSED_RESULT;
kj::Array<kj::byte> computeSecret(kj::ArrayPtr<kj::byte> key) KJ_WARN_UNUSED_RESULT;
kj::Array<kj::byte> generateKeys() KJ_WARN_UNUSED_RESULT;
jsg::BufferSource getPublicKey(jsg::Lock& js) KJ_WARN_UNUSED_RESULT;
jsg::BufferSource getPrivateKey(jsg::Lock& js) KJ_WARN_UNUSED_RESULT;
jsg::BufferSource getGenerator(jsg::Lock& js) KJ_WARN_UNUSED_RESULT;
jsg::BufferSource getPrime(jsg::Lock& js) KJ_WARN_UNUSED_RESULT;
jsg::BufferSource computeSecret(jsg::Lock& js, kj::ArrayPtr<kj::byte> key) KJ_WARN_UNUSED_RESULT;
jsg::BufferSource generateKeys(jsg::Lock& js) KJ_WARN_UNUSED_RESULT;

kj::Maybe<int> check() KJ_WARN_UNUSED_RESULT;

Expand Down
17 changes: 17 additions & 0 deletions src/workerd/api/crypto/impl.c++
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,23 @@ kj::Maybe<kj::Array<kj::byte>> bignumToArrayPadded(const BIGNUM& n, size_t padde
return kj::mv(result);
}

kj::Maybe<jsg::BufferSource> bignumToArrayPadded(jsg::Lock& js, const BIGNUM& n) {
auto result = jsg::BackingStore::alloc<v8::ArrayBuffer>(js, BN_num_bytes(&n));
if (BN_bn2binpad(&n, result.asArrayPtr().begin(), result.size()) != result.size()) {
return kj::none;
}
return jsg::BufferSource(js, kj::mv(result));
}

kj::Maybe<jsg::BufferSource> bignumToArrayPadded(
jsg::Lock& js, const BIGNUM& n, size_t paddedLength) {
auto result = jsg::BackingStore::alloc<v8::ArrayBuffer>(js, paddedLength);
if (BN_bn2bin_padded(result.asArrayPtr().begin(), paddedLength, &n) == 0) {
return kj::none;
}
return jsg::BufferSource(js, kj::mv(result));
}

kj::Own<BIGNUM> newBignum() {
return kj::Own<BIGNUM>(BN_new(), workerd::api::SslDisposer<BIGNUM, &BIGNUM_free>::INSTANCE);
}
Expand Down
3 changes: 3 additions & 0 deletions src/workerd/api/crypto/impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,9 @@ BIGNUM* toBignumUnowned(kj::ArrayPtr<const kj::byte> data);
kj::Maybe<kj::Array<kj::byte>> bignumToArray(const BIGNUM& bignum);
kj::Maybe<kj::Array<kj::byte>> bignumToArrayPadded(const BIGNUM& bignum);
kj::Maybe<kj::Array<kj::byte>> bignumToArrayPadded(const BIGNUM& bignum, size_t paddedLength);
kj::Maybe<jsg::BufferSource> bignumToArrayPadded(jsg::Lock& js, const BIGNUM& bignum);
kj::Maybe<jsg::BufferSource> bignumToArrayPadded(
jsg::Lock& js, const BIGNUM& bignum, size_t paddedLength);
kj::Own<BIGNUM> newBignum();

#define OSSL_BIO_MEM() \
Expand Down
7 changes: 5 additions & 2 deletions src/workerd/api/crypto/prime.c++
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
#include "prime.h"

#include <workerd/api/crypto/impl.h>
#include <workerd/jsg/jsg.h>

#include <openssl/bn.h>

namespace workerd::api {

kj::Array<kj::byte> randomPrime(uint32_t size,
jsg::BufferSource randomPrime(jsg::Lock& js,
uint32_t size,
bool safe,
kj::Maybe<kj::ArrayPtr<kj::byte>> add_buf,
kj::Maybe<kj::ArrayPtr<kj::byte>> rem_buf) {
Expand Down Expand Up @@ -85,7 +87,8 @@ kj::Array<kj::byte> randomPrime(uint32_t size,
int ret = BN_generate_prime_ex(prime.get(), bits, safe ? 1 : 0, add, rem, nullptr);
JSG_REQUIRE(ret == 1, Error, "Error while generating prime");

return JSG_REQUIRE_NONNULL(bignumToArrayPadded(*prime), Error, "Error while generating prime");
return JSG_REQUIRE_NONNULL(
bignumToArrayPadded(js, *prime), Error, "Error while generating prime");
}

bool checkPrime(kj::ArrayPtr<kj::byte> bufferView, uint32_t num_checks) {
Expand Down
8 changes: 7 additions & 1 deletion src/workerd/api/crypto/prime.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,16 @@

#include <cstdint>

namespace workerd::jsg {
class Lock;
class BufferSource;
} // namespace workerd::jsg

namespace workerd::api {

// Generate a random prime number
kj::Array<kj::byte> randomPrime(uint32_t size,
jsg::BufferSource randomPrime(jsg::Lock& js,
uint32_t size,
bool safe,
kj::Maybe<kj::ArrayPtr<kj::byte>> add_buf,
kj::Maybe<kj::ArrayPtr<kj::byte>> rem_buf);
Expand Down
30 changes: 16 additions & 14 deletions src/workerd/api/node/crypto.c++
Original file line number Diff line number Diff line change
Expand Up @@ -103,11 +103,12 @@ kj::Maybe<jsg::BufferSource> CryptoImpl::exportChallenge(
return workerd::api::exportChallenge(js, input);
}

kj::Array<kj::byte> CryptoImpl::randomPrime(uint32_t size,
jsg::BufferSource CryptoImpl::randomPrime(jsg::Lock& js,
uint32_t size,
bool safe,
jsg::Optional<kj::Array<kj::byte>> add_buf,
jsg::Optional<kj::Array<kj::byte>> rem_buf) {
return workerd::api::randomPrime(size, safe,
return workerd::api::randomPrime(js, size, safe,
add_buf.map([](kj::Array<kj::byte>& buf) { return buf.asPtr(); }),
rem_buf.map([](kj::Array<kj::byte>& buf) { return buf.asPtr(); }));
}
Expand Down Expand Up @@ -216,28 +217,29 @@ void CryptoImpl::DiffieHellmanHandle::setPublicKey(kj::Array<kj::byte> key) {
dh.setPublicKey(key);
}

kj::Array<kj::byte> CryptoImpl::DiffieHellmanHandle::getPublicKey() {
return dh.getPublicKey();
jsg::BufferSource CryptoImpl::DiffieHellmanHandle::getPublicKey(jsg::Lock& js) {
return dh.getPublicKey(js);
}

kj::Array<kj::byte> CryptoImpl::DiffieHellmanHandle::getPrivateKey() {
return dh.getPrivateKey();
jsg::BufferSource CryptoImpl::DiffieHellmanHandle::getPrivateKey(jsg::Lock& js) {
return dh.getPrivateKey(js);
}

kj::Array<kj::byte> CryptoImpl::DiffieHellmanHandle::getGenerator() {
return dh.getGenerator();
jsg::BufferSource CryptoImpl::DiffieHellmanHandle::getGenerator(jsg::Lock& js) {
return dh.getGenerator(js);
}

kj::Array<kj::byte> CryptoImpl::DiffieHellmanHandle::getPrime() {
return dh.getPrime();
jsg::BufferSource CryptoImpl::DiffieHellmanHandle::getPrime(jsg::Lock& js) {
return dh.getPrime(js);
}

kj::Array<kj::byte> CryptoImpl::DiffieHellmanHandle::computeSecret(kj::Array<kj::byte> key) {
return dh.computeSecret(key);
jsg::BufferSource CryptoImpl::DiffieHellmanHandle::computeSecret(
jsg::Lock& js, kj::Array<kj::byte> key) {
return dh.computeSecret(js, key);
}

kj::Array<kj::byte> CryptoImpl::DiffieHellmanHandle::generateKeys() {
return dh.generateKeys();
jsg::BufferSource CryptoImpl::DiffieHellmanHandle::generateKeys(jsg::Lock& js) {
return dh.generateKeys(js);
}

int CryptoImpl::DiffieHellmanHandle::getVerifyError() {
Expand Down
15 changes: 8 additions & 7 deletions src/workerd/api/node/crypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ class CryptoImpl final: public jsg::Object {

void setPrivateKey(kj::Array<kj::byte> key);
void setPublicKey(kj::Array<kj::byte> key);
kj::Array<kj::byte> getPublicKey();
kj::Array<kj::byte> getPrivateKey();
kj::Array<kj::byte> getGenerator();
kj::Array<kj::byte> getPrime();
kj::Array<kj::byte> computeSecret(kj::Array<kj::byte> key);
kj::Array<kj::byte> generateKeys();
jsg::BufferSource getPublicKey(jsg::Lock& js);
jsg::BufferSource getPrivateKey(jsg::Lock& js);
jsg::BufferSource getGenerator(jsg::Lock& js);
jsg::BufferSource getPrime(jsg::Lock& js);
jsg::BufferSource computeSecret(jsg::Lock& js, kj::Array<kj::byte> key);
jsg::BufferSource generateKeys(jsg::Lock& js);
int getVerifyError();

JSG_RESOURCE_TYPE(DiffieHellmanHandle) {
Expand All @@ -52,7 +52,8 @@ class CryptoImpl final: public jsg::Object {
jsg::Ref<DiffieHellmanHandle> DiffieHellmanGroupHandle(kj::String name);

// Primes
kj::Array<kj::byte> randomPrime(uint32_t size,
jsg::BufferSource randomPrime(jsg::Lock& js,
uint32_t size,
bool safe,
jsg::Optional<kj::Array<kj::byte>> add,
jsg::Optional<kj::Array<kj::byte>> rem);
Expand Down

0 comments on commit 159766b

Please sign in to comment.