Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
src: update ECDASSigPointer implementation in ncrypto
  • Loading branch information
jasnell committed Jan 8, 2025
commit a64ad443ab47e9ab0d5b95a5a69b976fc28f450c
64 changes: 64 additions & 0 deletions deps/ncrypto/ncrypto.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2613,4 +2613,68 @@ bool CipherCtxPointer::getAeadTag(size_t len, unsigned char* out) {
return EVP_CIPHER_CTX_ctrl(ctx_.get(), EVP_CTRL_AEAD_GET_TAG, len, out);
}

// ============================================================================

ECDSASigPointer::ECDSASigPointer() : sig_(nullptr) {}
ECDSASigPointer::ECDSASigPointer(ECDSA_SIG* sig) : sig_(sig) {
if (sig_) {
ECDSA_SIG_get0(sig_.get(), &pr_, &ps_);
}
}
ECDSASigPointer::ECDSASigPointer(ECDSASigPointer&& other) noexcept
: sig_(other.release()) {
if (sig_) {
ECDSA_SIG_get0(sig_.get(), &pr_, &ps_);
}
}

ECDSASigPointer& ECDSASigPointer::operator=(ECDSASigPointer&& other) noexcept {
sig_.reset(other.release());
if (sig_) {
ECDSA_SIG_get0(sig_.get(), &pr_, &ps_);
}
return *this;
}

ECDSASigPointer::~ECDSASigPointer() {
reset();
}

void ECDSASigPointer::reset(ECDSA_SIG* sig) {
sig_.reset();
pr_ = nullptr;
ps_ = nullptr;
}

ECDSA_SIG* ECDSASigPointer::release() {
pr_ = nullptr;
ps_ = nullptr;
return sig_.release();
}

ECDSASigPointer ECDSASigPointer::New() {
return ECDSASigPointer(ECDSA_SIG_new());
}

ECDSASigPointer ECDSASigPointer::Parse(const Buffer<const unsigned char>& sig) {
const unsigned char* ptr = sig.data;
return ECDSASigPointer(d2i_ECDSA_SIG(nullptr, &ptr, sig.len));
}

bool ECDSASigPointer::setParams(BignumPointer&& r, BignumPointer&& s) {
if (!sig_) return false;
return ECDSA_SIG_set0(sig_.get(), r.release(), s.release());
}

Buffer<unsigned char> ECDSASigPointer::encode() const {
if (!sig_)
return {
.data = nullptr,
.len = 0,
};
Buffer<unsigned char> buf;
buf.len = i2d_ECDSA_SIG(sig_.get(), &buf.data);
return buf;
}

} // namespace ncrypto
33 changes: 32 additions & 1 deletion deps/ncrypto/ncrypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,6 @@ using DeleteFnPtr = typename FunctionDeleter<T, function>::Pointer;

using BignumCtxPointer = DeleteFnPtr<BN_CTX, BN_CTX_free>;
using BignumGenCallbackPointer = DeleteFnPtr<BN_GENCB, BN_GENCB_free>;
using ECDSASigPointer = DeleteFnPtr<ECDSA_SIG, ECDSA_SIG_free>;
using ECGroupPointer = DeleteFnPtr<EC_GROUP, EC_GROUP_free>;
using ECKeyPointer = DeleteFnPtr<EC_KEY, EC_KEY_free>;
using ECPointPointer = DeleteFnPtr<EC_POINT, EC_POINT_free>;
Expand Down Expand Up @@ -821,6 +820,38 @@ class X509Pointer final {
DeleteFnPtr<X509, X509_free> cert_;
};

class ECDSASigPointer final {
public:
explicit ECDSASigPointer();
explicit ECDSASigPointer(ECDSA_SIG* sig);
ECDSASigPointer(ECDSASigPointer&& other) noexcept;
ECDSASigPointer& operator=(ECDSASigPointer&& other) noexcept;
NCRYPTO_DISALLOW_COPY(ECDSASigPointer)
~ECDSASigPointer();

inline bool operator==(std::nullptr_t) noexcept { return sig_ == nullptr; }
inline operator bool() const { return sig_ != nullptr; }
inline ECDSA_SIG* get() const { return sig_.get(); }
inline operator ECDSA_SIG*() const { return sig_.get(); }
void reset(ECDSA_SIG* sig = nullptr);
ECDSA_SIG* release();

static ECDSASigPointer New();
static ECDSASigPointer Parse(const Buffer<const unsigned char>& buffer);

inline const BIGNUM* r() const { return pr_; }
inline const BIGNUM* s() const { return ps_; }

bool setParams(BignumPointer&& r, BignumPointer&& s);

Buffer<unsigned char> encode() const;

private:
DeleteFnPtr<ECDSA_SIG, ECDSA_SIG_free> sig_;
const BIGNUM* pr_ = nullptr;
const BIGNUM* ps_ = nullptr;
};

#ifndef OPENSSL_NO_ENGINE
class EnginePointer final {
public:
Expand Down
30 changes: 13 additions & 17 deletions src/crypto/crypto_sig.cc
Original file line number Diff line number Diff line change
Expand Up @@ -150,16 +150,16 @@ bool ExtractP1363(
unsigned char* out,
size_t len,
size_t n) {
ECDSASigPointer asn1_sig(d2i_ECDSA_SIG(nullptr, &sig_data, len));
ncrypto::Buffer<const unsigned char> sig_buffer{
.data = sig_data,
.len = len,
};
auto asn1_sig = ECDSASigPointer::Parse(sig_buffer);
if (!asn1_sig)
return false;

const BIGNUM* pr;
const BIGNUM* ps;
ECDSA_SIG_get0(asn1_sig.get(), &pr, &ps);

return BignumPointer::EncodePaddedInto(pr, out, n) > 0 &&
BignumPointer::EncodePaddedInto(ps, out + n, n) > 0;
return BignumPointer::EncodePaddedInto(asn1_sig.r(), out, n) > 0 &&
BignumPointer::EncodePaddedInto(asn1_sig.s(), out + n, n) > 0;
}

// Returns the maximum size of each of the integers (r, s) of the DSA signature.
Expand Down Expand Up @@ -213,23 +213,19 @@ ByteSource ConvertSignatureToDER(const EVPKeyPointer& pkey, ByteSource&& out) {
if (out.size() != 2 * n)
return ByteSource();

ECDSASigPointer asn1_sig(ECDSA_SIG_new());
auto asn1_sig = ECDSASigPointer::New();
CHECK(asn1_sig);
BignumPointer r(sig_data, n);
CHECK(r);
BignumPointer s(sig_data + n, n);
CHECK(s);
CHECK_EQ(1, ECDSA_SIG_set0(asn1_sig.get(), r.release(), s.release()));

unsigned char* data = nullptr;
int len = i2d_ECDSA_SIG(asn1_sig.get(), &data);

if (len <= 0)
return ByteSource();
CHECK(asn1_sig.setParams(std::move(r), std::move(s)));

CHECK_NOT_NULL(data);
auto buf = asn1_sig.encode();
if (buf.len <= 0) return ByteSource();

return ByteSource::Allocated(data, len);
CHECK_NOT_NULL(buf.data);
return ByteSource::Allocated(buf);
}

void CheckThrow(Environment* env, SignBase::Error error) {
Expand Down
2 changes: 1 addition & 1 deletion test/cctest/test_node_crypto_env.cc
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
#include <ncrypto.h>
#include "crypto/crypto_bio.h"
#include "gtest/gtest.h"
#include "node_options.h"
#include "node_test_fixture.h"
#include "openssl/err.h"
#include <ncrypto.h>

using v8::Local;
using v8::String;
Expand Down