Skip to content

Commit 4f27d7c

Browse files
authored
fix(ext/node): GCM auth tag check on DechiperIv#final (#27733)
1 parent e4a16e9 commit 4f27d7c

File tree

5 files changed

+19
-24
lines changed

5 files changed

+19
-24
lines changed

ext/node/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,6 @@ deno_core::extension!(deno_node,
226226
ops::crypto::op_node_decipheriv_decrypt,
227227
ops::crypto::op_node_decipheriv_final,
228228
ops::crypto::op_node_decipheriv_set_aad,
229-
ops::crypto::op_node_decipheriv_take,
230229
ops::crypto::op_node_dh_compute_secret,
231230
ops::crypto::op_node_diffie_hellman,
232231
ops::crypto::op_node_ecdh_compute_public_key,

ext/node/ops/crypto/cipher.rs

+5
Original file line numberDiff line numberDiff line change
@@ -500,6 +500,11 @@ impl Decipher {
500500
auth_tag: &[u8],
501501
) -> Result<(), DecipherError> {
502502
use Decipher::*;
503+
504+
if input.is_empty() && !matches!(self, Aes128Gcm(_) | Aes256Gcm(_)) {
505+
return Ok(());
506+
}
507+
503508
match (self, auto_pad) {
504509
(Aes128Cbc(decryptor), true) => {
505510
assert!(input.len() == 16);

ext/node/ops/crypto/mod.rs

-11
Original file line numberDiff line numberDiff line change
@@ -332,17 +332,6 @@ pub fn op_node_decipheriv_decrypt(
332332
true
333333
}
334334

335-
#[op2(fast)]
336-
pub fn op_node_decipheriv_take(
337-
state: &mut OpState,
338-
#[smi] rid: u32,
339-
) -> Result<(), cipher::DecipherContextError> {
340-
let context = state.resource_table.take::<cipher::DecipherContext>(rid)?;
341-
Rc::try_unwrap(context)
342-
.map_err(|_| cipher::DecipherContextError::ContextInUse)?;
343-
Ok(())
344-
}
345-
346335
#[op2]
347336
pub fn op_node_decipheriv_final(
348337
state: &mut OpState,

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

+7-9
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import {
1818
op_node_decipheriv_decrypt,
1919
op_node_decipheriv_final,
2020
op_node_decipheriv_set_aad,
21-
op_node_decipheriv_take,
2221
op_node_private_decrypt,
2322
op_node_private_encrypt,
2423
op_node_public_encrypt,
@@ -352,14 +351,6 @@ export class Decipheriv extends Transform implements Cipher {
352351
}
353352

354353
final(encoding: string = getDefaultEncoding()): Buffer | string {
355-
if (!this.#needsBlockCache || this.#cache.cache.byteLength === 0) {
356-
op_node_decipheriv_take(this.#context);
357-
return encoding === "buffer" ? Buffer.from([]) : "";
358-
}
359-
if (this.#cache.cache.byteLength != 16) {
360-
throw new Error("Invalid final block size");
361-
}
362-
363354
let buf = new Buffer(16);
364355
op_node_decipheriv_final(
365356
this.#context,
@@ -369,6 +360,13 @@ export class Decipheriv extends Transform implements Cipher {
369360
this.#authTag || NO_TAG,
370361
);
371362

363+
if (!this.#needsBlockCache || this.#cache.cache.byteLength === 0) {
364+
return encoding === "buffer" ? Buffer.from([]) : "";
365+
}
366+
if (this.#cache.cache.byteLength != 16) {
367+
throw new Error("Invalid final block size");
368+
}
369+
372370
buf = buf.subarray(0, 16 - buf.at(-1)); // Padded in Pkcs7 mode
373371
return encoding === "buffer" ? buf : buf.toString(encoding);
374372
}

tests/unit_node/crypto/crypto_cipher_gcm_test.ts

+7-3
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import crypto from "node:crypto";
44
import { Buffer } from "node:buffer";
55
import testVectors128 from "./gcmEncryptExtIV128.json" with { type: "json" };
66
import testVectors256 from "./gcmEncryptExtIV256.json" with { type: "json" };
7-
import { assertEquals } from "@std/assert";
7+
import { assertEquals, assertThrows } from "@std/assert";
88

99
const aesGcm = (bits: string, key: Uint8Array) => {
1010
const ALGO = bits == "128" ? `aes-128-gcm` : `aes-256-gcm`;
@@ -123,7 +123,7 @@ Deno.test({
123123
// Issue #27441
124124
// https://github.com/denoland/deno/issues/27441
125125
Deno.test({
126-
name: "aes-256-gcm supports IV of non standard length",
126+
name: "aes-256-gcm supports IV of non standard length and auth tag check",
127127
fn() {
128128
const decipher = crypto.createDecipheriv(
129129
"aes-256-gcm",
@@ -136,6 +136,10 @@ Deno.test({
136136
"utf-8",
137137
);
138138
assertEquals(decrypted, "this is a secret");
139-
decipher.final();
139+
assertThrows(
140+
() => decipher.final(),
141+
TypeError,
142+
"Failed to authenticate data",
143+
);
140144
},
141145
});

0 commit comments

Comments
 (0)