mirror of
https://github.com/denoland/deno.git
synced 2025-01-21 04:52:26 -05:00
fix(ext/node): GCM auth tag check on DechiperIv#final (#27733)
This commit is contained in:
parent
e4a16e91fa
commit
4f27d7cdc0
5 changed files with 19 additions and 24 deletions
|
@ -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,
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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",
|
||||||
|
);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
Loading…
Add table
Reference in a new issue