Skip to content

Commit

Permalink
crypto: reconcile duplicated code
Browse files Browse the repository at this point in the history
Signed-off-by: James M Snell <jasnell@gmail.com>

PR-URL: #37704
Reviewed-By: Filip Skokan <panva.ip@gmail.com>
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
  • Loading branch information
jasnell authored and danielleadams committed Mar 16, 2021
1 parent 764aa2d commit 341ee31
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 140 deletions.
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

0 comments on commit 341ee31

Please sign in to comment.