1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-01-20 20:42:19 -05:00

fix(ext/node): GCM auth tag check on DechiperIv#final (#27733)

This commit is contained in:
Divy Srivastava 2025-01-20 18:16:44 +05:30 committed by GitHub
parent e4a16e91fa
commit 4f27d7cdc0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 19 additions and 24 deletions

View file

@ -226,7 +226,6 @@ deno_core::extension!(deno_node,
ops::crypto::op_node_decipheriv_decrypt, ops::crypto::op_node_decipheriv_decrypt,
ops::crypto::op_node_decipheriv_final, ops::crypto::op_node_decipheriv_final,
ops::crypto::op_node_decipheriv_set_aad, ops::crypto::op_node_decipheriv_set_aad,
ops::crypto::op_node_decipheriv_take,
ops::crypto::op_node_dh_compute_secret, ops::crypto::op_node_dh_compute_secret,
ops::crypto::op_node_diffie_hellman, ops::crypto::op_node_diffie_hellman,
ops::crypto::op_node_ecdh_compute_public_key, ops::crypto::op_node_ecdh_compute_public_key,

View file

@ -500,6 +500,11 @@ impl Decipher {
auth_tag: &[u8], auth_tag: &[u8],
) -> Result<(), DecipherError> { ) -> Result<(), DecipherError> {
use Decipher::*; use Decipher::*;
if input.is_empty() && !matches!(self, Aes128Gcm(_) | Aes256Gcm(_)) {
return Ok(());
}
match (self, auto_pad) { match (self, auto_pad) {
(Aes128Cbc(decryptor), true) => { (Aes128Cbc(decryptor), true) => {
assert!(input.len() == 16); assert!(input.len() == 16);

View file

@ -332,17 +332,6 @@ pub fn op_node_decipheriv_decrypt(
true true
} }
#[op2(fast)]
pub fn op_node_decipheriv_take(
state: &mut OpState,
#[smi] rid: u32,
) -> Result<(), cipher::DecipherContextError> {
let context = state.resource_table.take::<cipher::DecipherContext>(rid)?;
Rc::try_unwrap(context)
.map_err(|_| cipher::DecipherContextError::ContextInUse)?;
Ok(())
}
#[op2] #[op2]
pub fn op_node_decipheriv_final( pub fn op_node_decipheriv_final(
state: &mut OpState, state: &mut OpState,

View file

@ -18,7 +18,6 @@ import {
op_node_decipheriv_decrypt, op_node_decipheriv_decrypt,
op_node_decipheriv_final, op_node_decipheriv_final,
op_node_decipheriv_set_aad, op_node_decipheriv_set_aad,
op_node_decipheriv_take,
op_node_private_decrypt, op_node_private_decrypt,
op_node_private_encrypt, op_node_private_encrypt,
op_node_public_encrypt, op_node_public_encrypt,
@ -352,14 +351,6 @@ export class Decipheriv extends Transform implements Cipher {
} }
final(encoding: string = getDefaultEncoding()): Buffer | string { final(encoding: string = getDefaultEncoding()): Buffer | string {
if (!this.#needsBlockCache || this.#cache.cache.byteLength === 0) {
op_node_decipheriv_take(this.#context);
return encoding === "buffer" ? Buffer.from([]) : "";
}
if (this.#cache.cache.byteLength != 16) {
throw new Error("Invalid final block size");
}
let buf = new Buffer(16); let buf = new Buffer(16);
op_node_decipheriv_final( op_node_decipheriv_final(
this.#context, this.#context,
@ -369,6 +360,13 @@ export class Decipheriv extends Transform implements Cipher {
this.#authTag || NO_TAG, this.#authTag || NO_TAG,
); );
if (!this.#needsBlockCache || this.#cache.cache.byteLength === 0) {
return encoding === "buffer" ? Buffer.from([]) : "";
}
if (this.#cache.cache.byteLength != 16) {
throw new Error("Invalid final block size");
}
buf = buf.subarray(0, 16 - buf.at(-1)); // Padded in Pkcs7 mode buf = buf.subarray(0, 16 - buf.at(-1)); // Padded in Pkcs7 mode
return encoding === "buffer" ? buf : buf.toString(encoding); return encoding === "buffer" ? buf : buf.toString(encoding);
} }

View file

@ -4,7 +4,7 @@ import crypto from "node:crypto";
import { Buffer } from "node:buffer"; import { Buffer } from "node:buffer";
import testVectors128 from "./gcmEncryptExtIV128.json" with { type: "json" }; import testVectors128 from "./gcmEncryptExtIV128.json" with { type: "json" };
import testVectors256 from "./gcmEncryptExtIV256.json" with { type: "json" }; import testVectors256 from "./gcmEncryptExtIV256.json" with { type: "json" };
import { assertEquals } from "@std/assert"; import { assertEquals, assertThrows } from "@std/assert";
const aesGcm = (bits: string, key: Uint8Array) => { const aesGcm = (bits: string, key: Uint8Array) => {
const ALGO = bits == "128" ? `aes-128-gcm` : `aes-256-gcm`; const ALGO = bits == "128" ? `aes-128-gcm` : `aes-256-gcm`;
@ -123,7 +123,7 @@ Deno.test({
// Issue #27441 // Issue #27441
// https://github.com/denoland/deno/issues/27441 // https://github.com/denoland/deno/issues/27441
Deno.test({ Deno.test({
name: "aes-256-gcm supports IV of non standard length", name: "aes-256-gcm supports IV of non standard length and auth tag check",
fn() { fn() {
const decipher = crypto.createDecipheriv( const decipher = crypto.createDecipheriv(
"aes-256-gcm", "aes-256-gcm",
@ -136,6 +136,10 @@ Deno.test({
"utf-8", "utf-8",
); );
assertEquals(decrypted, "this is a secret"); assertEquals(decrypted, "this is a secret");
decipher.final(); assertThrows(
() => decipher.final(),
TypeError,
"Failed to authenticate data",
);
}, },
}); });