Skip to content

Commit 64ba898

Browse files
divybotlittledivy
andauthored
fix(ext/node): set OSSL error codes and key-type checks in stateless diffieHellman (#33772)
## Summary Enables `test-crypto-dh-stateless` in node_compat suite. ## Test plan - [x] `cargo test --test node_compat -- test-crypto-dh-stateless` Co-authored-by: Divy Srivastava <me@littledivy.com>
1 parent 0049368 commit 64ba898

2 files changed

Lines changed: 44 additions & 11 deletions

File tree

ext/node/polyfills/internal/crypto/diffiehellman.ts

Lines changed: 43 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import {
2121
} from "ext:deno_node/internal/util/types.ts";
2222
import {
2323
ERR_CRYPTO_ECDH_INVALID_FORMAT,
24+
ERR_CRYPTO_INCOMPATIBLE_KEY,
2425
ERR_CRYPTO_UNKNOWN_DH_GROUP,
2526
ERR_INVALID_ARG_TYPE,
2627
ERR_INVALID_ARG_VALUE,
@@ -1539,6 +1540,45 @@ ECDH.prototype.setPublicKey = deprecate(
15391540
"DEP0031",
15401541
);
15411542

1543+
function statelessDH(
1544+
privateKeyObject: KeyObject,
1545+
publicKeyObject: KeyObject,
1546+
): Buffer {
1547+
// getKeyObjectHandle validates key.type and throws ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE
1548+
// for incompatible key kinds (e.g. secret instead of private), so we must
1549+
// call it before doing the asymmetricKeyType cross-check below.
1550+
const privateKey = getKeyObjectHandle(privateKeyObject, kConsumePrivate);
1551+
const publicKey = getKeyObjectHandle(publicKeyObject, kConsumePublic);
1552+
1553+
// Check that the asymmetric key types are compatible. EC and DH report
1554+
// mismatching domain parameters from the underlying op when the curves or
1555+
// group parameters differ; everything else (e.g. x25519 vs x448) is a key
1556+
// type mismatch and should surface as ERR_CRYPTO_INCOMPATIBLE_KEY.
1557+
const privType = privateKeyObject.asymmetricKeyType;
1558+
const pubType = publicKeyObject.asymmetricKeyType;
1559+
if (privType !== undefined && pubType !== undefined && privType !== pubType) {
1560+
throw new ERR_CRYPTO_INCOMPATIBLE_KEY(
1561+
"key types for Diffie-Hellman",
1562+
`${privType} and ${pubType}`,
1563+
);
1564+
}
1565+
1566+
try {
1567+
const bytes = op_node_diffie_hellman(privateKey, publicKey);
1568+
return Buffer.from(bytes);
1569+
} catch (err) {
1570+
const e = err as Error & { code?: string };
1571+
if (e && typeof e.message === "string") {
1572+
if (e.message.includes("mismatching domain parameters")) {
1573+
e.code = "ERR_OSSL_MISMATCHING_DOMAIN_PARAMETERS";
1574+
} else if (e.message.includes("failed during derivation")) {
1575+
e.code = "ERR_OSSL_FAILED_DURING_DERIVATION";
1576+
}
1577+
}
1578+
throw e;
1579+
}
1580+
}
1581+
15421582
export function diffieHellman(
15431583
options: {
15441584
privateKey: KeyObject;
@@ -1563,23 +1603,15 @@ export function diffieHellman(
15631603

15641604
if (callback) {
15651605
try {
1566-
const privateKey = getKeyObjectHandle(
1567-
options.privateKey,
1568-
kConsumePrivate,
1569-
);
1570-
const publicKey = getKeyObjectHandle(options.publicKey, kConsumePublic);
1571-
const bytes = op_node_diffie_hellman(privateKey, publicKey);
1572-
callback(null, Buffer.from(bytes));
1606+
const secret = statelessDH(options.privateKey, options.publicKey);
1607+
callback(null, secret);
15731608
} catch (err) {
15741609
callback(err as Error);
15751610
}
15761611
return;
15771612
}
15781613

1579-
const privateKey = getKeyObjectHandle(options.privateKey, kConsumePrivate);
1580-
const publicKey = getKeyObjectHandle(options.publicKey, kConsumePublic);
1581-
const bytes = op_node_diffie_hellman(privateKey, publicKey);
1582-
return Buffer.from(bytes);
1614+
return statelessDH(options.privateKey, options.publicKey);
15831615
}
15841616

15851617
export default {

tests/node_compat/config.jsonc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,7 @@
487487
"parallel/test-crypto-dh-padding.js": {},
488488
"parallel/test-crypto-dh-shared.js": {},
489489
"parallel/test-crypto-dh-stateless-async.js": {},
490+
"parallel/test-crypto-dh-stateless.js": {},
490491
"parallel/test-crypto-dh.js": {},
491492
"parallel/test-crypto-domain.js": {},
492493
"parallel/test-crypto-domains.js": {},

0 commit comments

Comments
 (0)