Skip to content

Commit b7dead3

Browse files
committed
fixup! crypto: add optional callback to crypto.sign and crypto.verify
1 parent f85e838 commit b7dead3

File tree

10 files changed

+147
-65
lines changed

10 files changed

+147
-65
lines changed

lib/internal/crypto/dsa.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ const {
1010
KeyObjectHandle,
1111
SignJob,
1212
kCryptoJobAsync,
13+
kSigEncDER,
1314
kKeyTypePrivate,
1415
kSignJobModeSign,
1516
kSignJobModeVerify,
@@ -254,8 +255,8 @@ function dsaSignVerify(key, data, algorithm, signature) {
254255
normalizeHashName(key.algorithm.hash.name),
255256
undefined, // Salt-length is not used in DSA
256257
undefined, // Padding is not used in DSA
257-
kSigEncDER, // TODO(@jasnell): revise the inconsistency with WebCrypto's EC
258-
signature));
258+
signature,
259+
kSigEncDER));
259260
}
260261

261262
module.exports = {

lib/internal/crypto/ec.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -435,8 +435,8 @@ function ecdsaSignVerify(key, data, { name, hash }, signature) {
435435
hashname,
436436
undefined, // Salt length, not used with ECDSA
437437
undefined, // PSS Padding, not used with ECDSA
438-
kSigEncP1363,
439-
signature));
438+
signature,
439+
kSigEncP1363));
440440
}
441441

442442
module.exports = {

lib/internal/crypto/rsa.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,6 @@ function rsaSignVerify(key, data, { saltLength }, signature) {
360360
normalizeHashName(key.algorithm.hash.name),
361361
saltLength,
362362
padding,
363-
undefined, // EC(DSA) Signature Encoding is not used in RSA
364363
signature));
365364
}
366365

lib/internal/crypto/sig.js

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,6 @@ function signOneShot(algorithm, data, key, callback) {
183183
keyData = createPrivateKey(key)[kHandle];
184184
}
185185

186-
// TODO: add dsaSigEnc to SignJob
187186
// TODO: recognize pssSaltLength RSA_PSS_SALTLEN_* constants in SignJob
188187
const job = new SignJob(
189188
kCryptoJobAsync,
@@ -193,6 +192,7 @@ function signOneShot(algorithm, data, key, callback) {
193192
algorithm,
194193
pssSaltLength,
195194
rsaPadding,
195+
undefined,
196196
dsaSigEnc);
197197

198198
job.ondone = (error, signature) => {
@@ -295,7 +295,6 @@ function verifyOneShot(algorithm, data, key, signature, callback) {
295295
keyData = createPublicKey(key)[kHandle];
296296
}
297297

298-
// TODO: add dsaSigEnc to SignJob
299298
// TODO: recognize pssSaltLength RSA_PSS_SALTLEN_* constants in SignJob
300299
const job = new SignJob(
301300
kCryptoJobAsync,
@@ -305,8 +304,8 @@ function verifyOneShot(algorithm, data, key, signature, callback) {
305304
algorithm,
306305
pssSaltLength,
307306
rsaPadding,
308-
dsaSigEnc,
309-
signature);
307+
signature,
308+
dsaSigEnc);
310309

311310
job.ondone = (error, result) => {
312311
if (error) return FunctionPrototypeCall(callback, job, error);

src/crypto/crypto_ec.cc

Lines changed: 87 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -926,62 +926,114 @@ size_t GroupOrderSize(ManagedEVPPKey key) {
926926
return BN_num_bytes(order.get());
927927
}
928928

929+
// TODO(@jasnell): Reconcile with ConvertSignatureToP1363 in crypto_sig.cc
930+
// TODO(@jasnell): Move out of crypto_ec since this is also doing DSA now also
929931
ByteSource ConvertToWebCryptoSignature(
930-
ManagedEVPPKey key,
932+
const ManagedEVPPKey& key,
931933
const ByteSource& signature) {
932934
const unsigned char* data =
933935
reinterpret_cast<const unsigned char*>(signature.get());
934-
EcdsaSigPointer ecsig(d2i_ECDSA_SIG(nullptr, &data, signature.size()));
935-
936-
if (!ecsig)
937-
return ByteSource();
938-
939-
size_t order_size_bytes = GroupOrderSize(key);
940-
char* outdata = MallocOpenSSL<char>(order_size_bytes * 2);
941-
ByteSource out = ByteSource::Allocated(outdata, order_size_bytes * 2);
942-
unsigned char* ptr = reinterpret_cast<unsigned char*>(outdata);
943936

937+
ECDSASigPointer ecsig;
938+
DsaSigPointer dsasig;
944939
const BIGNUM* pr;
945940
const BIGNUM* ps;
946-
ECDSA_SIG_get0(ecsig.get(), &pr, &ps);
941+
size_t len = 0;
947942

948-
if (!BN_bn2binpad(pr, ptr, order_size_bytes) ||
949-
!BN_bn2binpad(ps, ptr + order_size_bytes, order_size_bytes)) {
943+
switch (EVP_PKEY_id(key.get())) {
944+
case EVP_PKEY_EC: {
945+
ecsig = ECDSASigPointer(d2i_ECDSA_SIG(nullptr, &data, signature.size()));
946+
947+
if (!ecsig)
948+
return ByteSource();
949+
950+
len = GroupOrderSize(key);
951+
952+
ECDSA_SIG_get0(ecsig.get(), &pr, &ps);
953+
break;
954+
}
955+
case EVP_PKEY_DSA: {
956+
dsasig = DsaSigPointer(d2i_DSA_SIG(nullptr, &data, signature.size()));
957+
958+
if (!dsasig)
959+
return ByteSource();
960+
961+
DSA_SIG_get0(dsasig.get(), &pr, &ps);
962+
len = BN_num_bytes(pr);
963+
}
964+
}
965+
966+
CHECK_GT(len, 0);
967+
968+
char* outdata = MallocOpenSSL<char>(len * 2);
969+
ByteSource out = ByteSource::Allocated(outdata, len * 2);
970+
unsigned char* ptr = reinterpret_cast<unsigned char*>(outdata);
971+
972+
if (!BN_bn2binpad(pr, ptr, len) || !BN_bn2binpad(ps, ptr + len, len)) {
950973
return ByteSource();
951974
}
952975
return out;
953976
}
954977

978+
// TODO(@jasnell): Reconcile with ConvertSignatureToDER in crypto_sig.cc
979+
// TODO(@jasnell): Move out of crypto_ec since this is also doing DSA now also
955980
ByteSource ConvertFromWebCryptoSignature(
956-
ManagedEVPPKey key,
981+
const ManagedEVPPKey& key,
957982
const ByteSource& signature) {
958-
size_t order_size_bytes = GroupOrderSize(key);
983+
BignumPointer r(BN_new());
984+
BignumPointer s(BN_new());
985+
const unsigned char* sig = signature.data<unsigned char>();
959986

960-
// If the size of the signature is incorrect, verification
961-
// will fail.
962-
if (signature.size() != 2 * order_size_bytes)
963-
return ByteSource(); // Empty!
987+
switch (EVP_PKEY_id(key.get())) {
988+
case EVP_PKEY_EC: {
989+
size_t order_size_bytes = GroupOrderSize(key);
964990

965-
EcdsaSigPointer ecsig(ECDSA_SIG_new());
966-
if (!ecsig)
967-
return ByteSource();
991+
// If the size of the signature is incorrect, verification
992+
// will fail.
993+
if (signature.size() != 2 * order_size_bytes)
994+
return ByteSource(); // Empty!
968995

969-
BignumPointer r(BN_new());
970-
BignumPointer s(BN_new());
996+
ECDSASigPointer ecsig(ECDSA_SIG_new());
997+
if (!ecsig)
998+
return ByteSource();
971999

972-
const unsigned char* sig = signature.data<unsigned char>();
1000+
if (!BN_bin2bn(sig, order_size_bytes, r.get()) ||
1001+
!BN_bin2bn(sig + order_size_bytes, order_size_bytes, s.get()) ||
1002+
!ECDSA_SIG_set0(ecsig.get(), r.release(), s.release())) {
1003+
return ByteSource();
1004+
}
9731005

974-
if (!BN_bin2bn(sig, order_size_bytes, r.get()) ||
975-
!BN_bin2bn(sig + order_size_bytes, order_size_bytes, s.get()) ||
976-
!ECDSA_SIG_set0(ecsig.get(), r.release(), s.release())) {
977-
return ByteSource();
978-
}
1006+
int size = i2d_ECDSA_SIG(ecsig.get(), nullptr);
1007+
char* data = MallocOpenSSL<char>(size);
1008+
unsigned char* ptr = reinterpret_cast<unsigned char*>(data);
1009+
CHECK_EQ(i2d_ECDSA_SIG(ecsig.get(), &ptr), size);
1010+
return ByteSource::Allocated(data, size);
1011+
}
1012+
case EVP_PKEY_DSA: {
1013+
size_t len = signature.size() / 2;
1014+
1015+
if (signature.size() != 2 * len)
1016+
return ByteSource();
1017+
1018+
DsaSigPointer dsasig(DSA_SIG_new());
1019+
if (!dsasig)
1020+
return ByteSource();
1021+
1022+
if (!BN_bin2bn(sig, len, r.get()) ||
1023+
!BN_bin2bn(sig + len, len, s.get()) ||
1024+
!DSA_SIG_set0(dsasig.get(), r.release(), s.release())) {
1025+
return ByteSource();
1026+
}
9791027

980-
int size = i2d_ECDSA_SIG(ecsig.get(), nullptr);
981-
char* data = MallocOpenSSL<char>(size);
982-
unsigned char* ptr = reinterpret_cast<unsigned char*>(data);
983-
CHECK_EQ(i2d_ECDSA_SIG(ecsig.get(), &ptr), size);
984-
return ByteSource::Allocated(data, size);
1028+
int size = i2d_DSA_SIG(dsasig.get(), nullptr);
1029+
char* data = MallocOpenSSL<char>(size);
1030+
unsigned char* ptr = reinterpret_cast<unsigned char*>(data);
1031+
CHECK_EQ(i2d_DSA_SIG(dsasig.get(), &ptr), size);
1032+
return ByteSource::Allocated(data, size);
1033+
}
1034+
default:
1035+
UNREACHABLE();
1036+
}
9851037
}
9861038

9871039
} // namespace crypto

src/crypto/crypto_ec.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,11 +164,11 @@ v8::Maybe<bool> GetEcKeyDetail(
164164
v8::Local<v8::Object> target);
165165

166166
ByteSource ConvertToWebCryptoSignature(
167-
ManagedEVPPKey key,
167+
const ManagedEVPPKey& key,
168168
const ByteSource& signature);
169169

170170
ByteSource ConvertFromWebCryptoSignature(
171-
ManagedEVPPKey key,
171+
const ManagedEVPPKey& key,
172172
const ByteSource& signature);
173173

174174
} // namespace crypto

src/crypto/crypto_sig.cc

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,14 @@ bool IsOneShot(const ManagedEVPPKey& key) {
233233
return false;
234234
}
235235
}
236+
237+
bool UseP1363Encoding(const SignConfiguration& params) {
238+
switch (EVP_PKEY_id(params.key->GetAsymmetricKey().get())) {
239+
case EVP_PKEY_EC:
240+
case EVP_PKEY_DSA: return params.dsa_encoding == kSigEncP1363;
241+
}
242+
return false;
243+
}
236244
} // namespace
237245

238246
SignBase::Error SignBase::Init(const char* sign_type) {
@@ -297,6 +305,8 @@ void Sign::Initialize(Environment* env, Local<Object> target) {
297305

298306
NODE_DEFINE_CONSTANT(target, kSignJobModeSign);
299307
NODE_DEFINE_CONSTANT(target, kSignJobModeVerify);
308+
NODE_DEFINE_CONSTANT(target, kSigEncDER);
309+
NODE_DEFINE_CONSTANT(target, kSigEncP1363);
300310
NODE_DEFINE_CONSTANT(target, RSA_PKCS1_PSS_PADDING);
301311
}
302312

@@ -681,7 +691,8 @@ SignConfiguration::SignConfiguration(SignConfiguration&& other) noexcept
681691
digest(other.digest),
682692
flags(other.flags),
683693
padding(other.padding),
684-
salt_length(other.salt_length) {}
694+
salt_length(other.salt_length),
695+
dsa_encoding(other.dsa_encoding) {}
685696

686697
SignConfiguration& SignConfiguration::operator=(
687698
SignConfiguration&& other) noexcept {
@@ -744,6 +755,16 @@ Maybe<bool> SignTraits::AdditionalConfig(
744755
params->padding = args[offset + 5].As<Uint32>()->Value();
745756
}
746757

758+
if (args[offset + 7]->IsUint32()) { // DSA Encoding
759+
params->dsa_encoding =
760+
static_cast<DSASigEnc>(args[offset + 7].As<Uint32>()->Value());
761+
if (params->dsa_encoding != kSigEncDER &&
762+
params->dsa_encoding != kSigEncP1363) {
763+
THROW_ERR_OUT_OF_RANGE(env, "invalid signature encoding");
764+
return Nothing<bool>();
765+
}
766+
}
767+
747768
if (params->mode == SignConfiguration::kVerify) {
748769
ArrayBufferOrViewContents<char> signature(args[offset + 6]);
749770
if (UNLIKELY(!signature.CheckSizeInt32())) {
@@ -754,7 +775,7 @@ Maybe<bool> SignTraits::AdditionalConfig(
754775
// the signature from WebCrypto format into DER format...
755776
ManagedEVPPKey m_pkey = params->key->GetAsymmetricKey();
756777
Mutex::ScopedLock lock(*m_pkey.mutex());
757-
if (EVP_PKEY_id(m_pkey.get()) == EVP_PKEY_EC) {
778+
if (UseP1363Encoding(*params)) {
758779
params->signature =
759780
ConvertFromWebCryptoSignature(m_pkey, signature.ToByteSource());
760781
} else {
@@ -851,9 +872,7 @@ bool SignTraits::DeriveBits(
851872
if (!EVP_DigestSignFinal(context.get(), data, &len))
852873
return false;
853874

854-
// If this is an EC key (assuming ECDSA) we have to
855-
// convert the signature in to the proper format.
856-
if (EVP_PKEY_id(params.key->GetAsymmetricKey().get()) == EVP_PKEY_EC) {
875+
if (UseP1363Encoding(params)) {
857876
*out = ConvertToWebCryptoSignature(
858877
params.key->GetAsymmetricKey(), buf);
859878
} else {

src/crypto/crypto_sig.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ namespace crypto {
1515
static const unsigned int kNoDsaSignature = static_cast<unsigned int>(-1);
1616

1717
enum DSASigEnc {
18-
kSigEncDER, kSigEncP1363
18+
kSigEncDER,
19+
kSigEncP1363
1920
};
2021

2122
class SignBase : public BaseObject {
@@ -117,6 +118,7 @@ struct SignConfiguration final : public MemoryRetainer {
117118
int flags = SignConfiguration::kHasNone;
118119
int padding = 0;
119120
int salt_length = 0;
121+
DSASigEnc dsa_encoding = kSigEncDER;
120122

121123
SignConfiguration() = default;
122124

src/crypto/crypto_util.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ using HMACCtxPointer = DeleteFnPtr<HMAC_CTX, HMAC_CTX_free>;
7070
using CipherCtxPointer = DeleteFnPtr<EVP_CIPHER_CTX, EVP_CIPHER_CTX_free>;
7171
using RsaPointer = DeleteFnPtr<RSA, RSA_free>;
7272
using DsaPointer = DeleteFnPtr<DSA, DSA_free>;
73-
using EcdsaSigPointer = DeleteFnPtr<ECDSA_SIG, ECDSA_SIG_free>;
73+
using DsaSigPointer = DeleteFnPtr<DSA_SIG, DSA_SIG_free>;
7474

7575
// Our custom implementation of the certificate verify callback
7676
// used when establishing a TLS handshake. Because we cannot perform

0 commit comments

Comments
 (0)