Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

crypto: reconcile duplicated code #37704

Closed
wants to merge 1 commit into from
Closed
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
114 changes: 0 additions & 114 deletions src/crypto/crypto_ec.cc
Original file line number Diff line number Diff line change
Expand Up @@ -927,119 +927,5 @@ size_t GroupOrderSize(ManagedEVPPKey key) {
CHECK(EC_GROUP_get_order(group, order.get(), nullptr));
return BN_num_bytes(order.get());
}

// TODO(@jasnell): Reconcile with ConvertSignatureToP1363 in crypto_sig.cc
// TODO(@jasnell): Move out of crypto_ec since this is also doing DSA now also
ByteSource ConvertToWebCryptoSignature(
const ManagedEVPPKey& key,
const ByteSource& signature) {
const unsigned char* data =
reinterpret_cast<const unsigned char*>(signature.get());

ECDSASigPointer ecsig;
DsaSigPointer dsasig;
const BIGNUM* pr;
const BIGNUM* ps;
size_t len = 0;

switch (EVP_PKEY_id(key.get())) {
case EVP_PKEY_EC: {
ecsig = ECDSASigPointer(d2i_ECDSA_SIG(nullptr, &data, signature.size()));

if (!ecsig)
return ByteSource();

len = GroupOrderSize(key);

ECDSA_SIG_get0(ecsig.get(), &pr, &ps);
break;
}
case EVP_PKEY_DSA: {
dsasig = DsaSigPointer(d2i_DSA_SIG(nullptr, &data, signature.size()));

if (!dsasig)
return ByteSource();

DSA_SIG_get0(dsasig.get(), &pr, &ps);
len = std::max(BN_num_bytes(pr), BN_num_bytes(ps));
}
}

CHECK_GT(len, 0);

char* outdata = MallocOpenSSL<char>(len * 2);
memset(outdata, 0, len * 2);
ByteSource out = ByteSource::Allocated(outdata, len * 2);
unsigned char* ptr = reinterpret_cast<unsigned char*>(outdata);

if (BN_bn2binpad(pr, ptr, len) <= 0 ||
BN_bn2binpad(ps, ptr + len, len) <= 0) {
return ByteSource();
}

return out;
}

// TODO(@jasnell): Reconcile with ConvertSignatureToDER in crypto_sig.cc
// TODO(@jasnell): Move out of crypto_ec since this is also doing DSA now also
ByteSource ConvertFromWebCryptoSignature(
const ManagedEVPPKey& key,
const ByteSource& signature) {
BignumPointer r(BN_new());
BignumPointer s(BN_new());
const unsigned char* sig = signature.data<unsigned char>();

switch (EVP_PKEY_id(key.get())) {
case EVP_PKEY_EC: {
size_t order_size_bytes = GroupOrderSize(key);

// If the size of the signature is incorrect, verification
// will fail.
if (signature.size() != 2 * order_size_bytes)
return ByteSource(); // Empty!

ECDSASigPointer ecsig(ECDSA_SIG_new());
if (!ecsig)
return ByteSource();

if (!BN_bin2bn(sig, order_size_bytes, r.get()) ||
!BN_bin2bn(sig + order_size_bytes, order_size_bytes, s.get()) ||
!ECDSA_SIG_set0(ecsig.get(), r.release(), s.release())) {
return ByteSource();
}

int size = i2d_ECDSA_SIG(ecsig.get(), nullptr);
char* data = MallocOpenSSL<char>(size);
unsigned char* ptr = reinterpret_cast<unsigned char*>(data);
CHECK_EQ(i2d_ECDSA_SIG(ecsig.get(), &ptr), size);
return ByteSource::Allocated(data, size);
}
case EVP_PKEY_DSA: {
size_t len = signature.size() / 2;

if (signature.size() != 2 * len)
return ByteSource();

DsaSigPointer dsasig(DSA_SIG_new());
if (!dsasig)
return ByteSource();

if (!BN_bin2bn(sig, len, r.get()) ||
!BN_bin2bn(sig + len, len, s.get()) ||
!DSA_SIG_set0(dsasig.get(), r.release(), s.release())) {
return ByteSource();
}

int size = i2d_DSA_SIG(dsasig.get(), nullptr);
char* data = MallocOpenSSL<char>(size);
unsigned char* ptr = reinterpret_cast<unsigned char*>(data);
CHECK_EQ(i2d_DSA_SIG(dsasig.get(), &ptr), size);
return ByteSource::Allocated(data, size);
}
default:
UNREACHABLE();
}
}

} // namespace crypto
} // namespace node
9 changes: 0 additions & 9 deletions src/crypto/crypto_ec.h
Original file line number Diff line number Diff line change
Expand Up @@ -162,15 +162,6 @@ v8::Maybe<bool> GetEcKeyDetail(
Environment* env,
std::shared_ptr<KeyObjectData> key,
v8::Local<v8::Object> target);

ByteSource ConvertToWebCryptoSignature(
const ManagedEVPPKey& key,
const ByteSource& signature);

ByteSource ConvertFromWebCryptoSignature(
const ManagedEVPPKey& key,
const ByteSource& signature);

} // namespace crypto
} // namespace node

Expand Down
67 changes: 50 additions & 17 deletions src/crypto/crypto_sig.cc
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,21 @@ unsigned int GetBytesOfRS(const ManagedEVPPKey& pkey) {
return (bits + 7) / 8;
}

bool ExtractP1363(
const unsigned char* sig_data,
unsigned char* out,
size_t len,
size_t n) {
ECDSASigPointer asn1_sig(d2i_ECDSA_SIG(nullptr, &sig_data, len));
if (!asn1_sig)
return false;

const BIGNUM* pr = ECDSA_SIG_get0_r(asn1_sig.get());
const BIGNUM* ps = ECDSA_SIG_get0_s(asn1_sig.get());

return BN_bn2binpad(pr, out, n) > 0 && BN_bn2binpad(ps, out + n, n) > 0;
}

// Returns the maximum size of each of the integers (r, s) of the DSA signature.
AllocatedBuffer ConvertSignatureToP1363(Environment* env,
const ManagedEVPPKey& pkey,
Expand All @@ -128,33 +143,49 @@ AllocatedBuffer ConvertSignatureToP1363(Environment* env,
const unsigned char* sig_data =
reinterpret_cast<unsigned char*>(signature.data());

ECDSASigPointer asn1_sig(d2i_ECDSA_SIG(nullptr, &sig_data, signature.size()));
if (!asn1_sig)
return AllocatedBuffer();

AllocatedBuffer buf = AllocatedBuffer::AllocateManaged(env, 2 * n);
unsigned char* data = reinterpret_cast<unsigned char*>(buf.data());

const BIGNUM* r = ECDSA_SIG_get0_r(asn1_sig.get());
const BIGNUM* s = ECDSA_SIG_get0_s(asn1_sig.get());
CHECK_EQ(n, static_cast<unsigned int>(BN_bn2binpad(r, data, n)));
CHECK_EQ(n, static_cast<unsigned int>(BN_bn2binpad(s, data + n, n)));
if (!ExtractP1363(sig_data, data, signature.size(), n))
return std::move(signature);

return buf;
}

// Returns the maximum size of each of the integers (r, s) of the DSA signature.
ByteSource ConvertSignatureToP1363(
Environment* env,
const ManagedEVPPKey& pkey,
const ByteSource& signature) {
unsigned int n = GetBytesOfRS(pkey);
if (n == kNoDsaSignature)
return ByteSource();

const unsigned char* sig_data =
reinterpret_cast<const unsigned char*>(signature.get());

char* outdata = MallocOpenSSL<char>(n * 2);
memset(outdata, 0, n * 2);
ByteSource out = ByteSource::Allocated(outdata, n * 2);
unsigned char* ptr = reinterpret_cast<unsigned char*>(outdata);

if (!ExtractP1363(sig_data, ptr, signature.size(), n))
return ByteSource();

return out;
}

ByteSource ConvertSignatureToDER(
const ManagedEVPPKey& pkey,
const ArrayBufferOrViewContents<char>& signature) {
ByteSource&& out) {
unsigned int n = GetBytesOfRS(pkey);
if (n == kNoDsaSignature)
return signature.ToByteSource();
return std::move(out);

const unsigned char* sig_data =
reinterpret_cast<const unsigned char*>(signature.data());
reinterpret_cast<const unsigned char*>(out.get());

if (signature.size() != 2 * n)
if (out.size() != 2 * n)
return ByteSource();

ECDSASigPointer asn1_sig(ECDSA_SIG_new());
Expand Down Expand Up @@ -511,7 +542,7 @@ void Verify::VerifyFinal(const FunctionCallbackInfo<Value>& args) {

ByteSource signature = hbuf.ToByteSource();
if (dsa_sig_enc == kSigEncP1363) {
signature = ConvertSignatureToDER(pkey, hbuf);
signature = ConvertSignatureToDER(pkey, hbuf.ToByteSource());
if (signature.get() == nullptr)
return crypto::CheckThrow(env, Error::kSignMalformedSignature);
}
Expand Down Expand Up @@ -657,7 +688,7 @@ void Verify::VerifySync(const FunctionCallbackInfo<Value>& args) {

ByteSource sig_bytes = ByteSource::Foreign(sig.data(), sig.size());
if (dsa_sig_enc == kSigEncP1363) {
sig_bytes = ConvertSignatureToDER(key, sig);
sig_bytes = ConvertSignatureToDER(key, sig.ToByteSource());
if (!sig_bytes)
return crypto::CheckThrow(env, SignBase::Error::kSignMalformedSignature);
}
Expand Down Expand Up @@ -778,7 +809,7 @@ Maybe<bool> SignTraits::AdditionalConfig(
Mutex::ScopedLock lock(*m_pkey.mutex());
if (UseP1363Encoding(m_pkey, params->dsa_encoding)) {
params->signature =
ConvertFromWebCryptoSignature(m_pkey, signature.ToByteSource());
ConvertSignatureToDER(m_pkey, signature.ToByteSource());
} else {
params->signature = mode == kCryptoJobAsync
? signature.ToCopy()
Expand Down Expand Up @@ -874,8 +905,10 @@ bool SignTraits::DeriveBits(
return false;

if (UseP1363Encoding(m_pkey, params.dsa_encoding)) {
*out = ConvertToWebCryptoSignature(
params.key->GetAsymmetricKey(), buf);
*out = ConvertSignatureToP1363(
env,
params.key->GetAsymmetricKey(),
buf);
} else {
buf.Resize(len);
*out = std::move(buf);
Expand Down