1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-11-24 15:19:26 -05:00

refactor: use concrete error type for remaining ops (#26746)

This commit is contained in:
Leo Kettmeir 2024-11-06 16:57:57 -08:00 committed by GitHub
parent db53ec230d
commit 1cab4f07a3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 1423 additions and 566 deletions

View file

@ -88,6 +88,10 @@ fn get_resolution_error_class(err: &ResolutionError) -> &'static str {
} }
} }
fn get_try_from_int_error_class(_: &std::num::TryFromIntError) -> &'static str {
"TypeError"
}
pub fn get_error_class_name(e: &AnyError) -> &'static str { pub fn get_error_class_name(e: &AnyError) -> &'static str {
deno_runtime::errors::get_error_class_name(e) deno_runtime::errors::get_error_class_name(e)
.or_else(|| { .or_else(|| {
@ -106,5 +110,9 @@ pub fn get_error_class_name(e: &AnyError) -> &'static str {
e.downcast_ref::<ResolutionError>() e.downcast_ref::<ResolutionError>()
.map(get_resolution_error_class) .map(get_resolution_error_class)
}) })
.or_else(|| {
e.downcast_ref::<std::num::TryFromIntError>()
.map(get_try_from_int_error_class)
})
.unwrap_or("Error") .unwrap_or("Error")
} }

View file

@ -56,7 +56,7 @@ struct PermissionsHolder(Uuid, PermissionsContainer);
pub fn op_pledge_test_permissions( pub fn op_pledge_test_permissions(
state: &mut OpState, state: &mut OpState,
#[serde] args: ChildPermissionsArg, #[serde] args: ChildPermissionsArg,
) -> Result<Uuid, AnyError> { ) -> Result<Uuid, deno_runtime::deno_permissions::ChildPermissionError> {
let token = Uuid::new_v4(); let token = Uuid::new_v4();
let parent_permissions = state.borrow_mut::<PermissionsContainer>(); let parent_permissions = state.borrow_mut::<PermissionsContainer>();
let worker_permissions = parent_permissions.create_child_permissions(args)?; let worker_permissions = parent_permissions.create_child_permissions(args)?;
@ -147,7 +147,7 @@ fn op_dispatch_bench_event(state: &mut OpState, #[serde] event: BenchEvent) {
#[op2(fast)] #[op2(fast)]
#[number] #[number]
fn op_bench_now(state: &mut OpState) -> Result<u64, AnyError> { fn op_bench_now(state: &mut OpState) -> Result<u64, std::num::TryFromIntError> {
let ns = state.borrow::<time::Instant>().elapsed().as_nanos(); let ns = state.borrow::<time::Instant>().elapsed().as_nanos();
let ns_u64 = u64::try_from(ns)?; let ns_u64 = u64::try_from(ns)?;
Ok(ns_u64) Ok(ns_u64)

View file

@ -46,7 +46,7 @@ pub fn op_jupyter_input(
state: &mut OpState, state: &mut OpState,
#[string] prompt: String, #[string] prompt: String,
is_password: bool, is_password: bool,
) -> Result<Option<String>, AnyError> { ) -> Option<String> {
let (last_execution_request, stdin_connection_proxy) = { let (last_execution_request, stdin_connection_proxy) = {
( (
state.borrow::<Arc<Mutex<Option<JupyterMessage>>>>().clone(), state.borrow::<Arc<Mutex<Option<JupyterMessage>>>>().clone(),
@ -58,11 +58,11 @@ pub fn op_jupyter_input(
if let Some(last_request) = maybe_last_request { if let Some(last_request) = maybe_last_request {
let JupyterMessageContent::ExecuteRequest(msg) = &last_request.content let JupyterMessageContent::ExecuteRequest(msg) = &last_request.content
else { else {
return Ok(None); return None;
}; };
if !msg.allow_stdin { if !msg.allow_stdin {
return Ok(None); return None;
} }
let content = InputRequest { let content = InputRequest {
@ -73,7 +73,7 @@ pub fn op_jupyter_input(
let msg = JupyterMessage::new(content, Some(&last_request)); let msg = JupyterMessage::new(content, Some(&last_request));
let Ok(()) = stdin_connection_proxy.lock().tx.send(msg) else { let Ok(()) = stdin_connection_proxy.lock().tx.send(msg) else {
return Ok(None); return None;
}; };
// Need to spawn a separate thread here, because `blocking_recv()` can't // Need to spawn a separate thread here, because `blocking_recv()` can't
@ -82,17 +82,25 @@ pub fn op_jupyter_input(
stdin_connection_proxy.lock().rx.blocking_recv() stdin_connection_proxy.lock().rx.blocking_recv()
}); });
let Ok(Some(response)) = join_handle.join() else { let Ok(Some(response)) = join_handle.join() else {
return Ok(None); return None;
}; };
let JupyterMessageContent::InputReply(msg) = response.content else { let JupyterMessageContent::InputReply(msg) = response.content else {
return Ok(None); return None;
}; };
return Ok(Some(msg.value)); return Some(msg.value);
} }
Ok(None) None
}
#[derive(Debug, thiserror::Error)]
pub enum JupyterBroadcastError {
#[error(transparent)]
SerdeJson(serde_json::Error),
#[error(transparent)]
ZeroMq(AnyError),
} }
#[op2(async)] #[op2(async)]
@ -102,7 +110,7 @@ pub async fn op_jupyter_broadcast(
#[serde] content: serde_json::Value, #[serde] content: serde_json::Value,
#[serde] metadata: serde_json::Value, #[serde] metadata: serde_json::Value,
#[serde] buffers: Vec<deno_core::JsBuffer>, #[serde] buffers: Vec<deno_core::JsBuffer>,
) -> Result<(), AnyError> { ) -> Result<(), JupyterBroadcastError> {
let (iopub_connection, last_execution_request) = { let (iopub_connection, last_execution_request) = {
let s = state.borrow(); let s = state.borrow();
@ -125,36 +133,35 @@ pub async fn op_jupyter_broadcast(
content, content,
err err
); );
err JupyterBroadcastError::SerdeJson(err)
})?; })?;
let jupyter_message = JupyterMessage::new(content, Some(&last_request)) let jupyter_message = JupyterMessage::new(content, Some(&last_request))
.with_metadata(metadata) .with_metadata(metadata)
.with_buffers(buffers.into_iter().map(|b| b.to_vec().into()).collect()); .with_buffers(buffers.into_iter().map(|b| b.to_vec().into()).collect());
iopub_connection.lock().send(jupyter_message).await?; iopub_connection
.lock()
.send(jupyter_message)
.await
.map_err(JupyterBroadcastError::ZeroMq)?;
} }
Ok(()) Ok(())
} }
#[op2(fast)] #[op2(fast)]
pub fn op_print( pub fn op_print(state: &mut OpState, #[string] msg: &str, is_err: bool) {
state: &mut OpState,
#[string] msg: &str,
is_err: bool,
) -> Result<(), AnyError> {
let sender = state.borrow_mut::<mpsc::UnboundedSender<StreamContent>>(); let sender = state.borrow_mut::<mpsc::UnboundedSender<StreamContent>>();
if is_err { if is_err {
if let Err(err) = sender.send(StreamContent::stderr(msg)) { if let Err(err) = sender.send(StreamContent::stderr(msg)) {
log::error!("Failed to send stderr message: {}", err); log::error!("Failed to send stderr message: {}", err);
} }
return Ok(()); return;
} }
if let Err(err) = sender.send(StreamContent::stdout(msg)) { if let Err(err) = sender.send(StreamContent::stdout(msg)) {
log::error!("Failed to send stdout message: {}", err); log::error!("Failed to send stdout message: {}", err);
} }
Ok(())
} }

View file

@ -51,7 +51,7 @@ struct PermissionsHolder(Uuid, PermissionsContainer);
pub fn op_pledge_test_permissions( pub fn op_pledge_test_permissions(
state: &mut OpState, state: &mut OpState,
#[serde] args: ChildPermissionsArg, #[serde] args: ChildPermissionsArg,
) -> Result<Uuid, AnyError> { ) -> Result<Uuid, deno_runtime::deno_permissions::ChildPermissionError> {
let token = Uuid::new_v4(); let token = Uuid::new_v4();
let parent_permissions = state.borrow_mut::<PermissionsContainer>(); let parent_permissions = state.borrow_mut::<PermissionsContainer>();
let worker_permissions = parent_permissions.create_child_permissions(args)?; let worker_permissions = parent_permissions.create_child_permissions(args)?;
@ -150,7 +150,7 @@ fn op_register_test_step(
#[smi] parent_id: usize, #[smi] parent_id: usize,
#[smi] root_id: usize, #[smi] root_id: usize,
#[string] root_name: String, #[string] root_name: String,
) -> Result<usize, AnyError> { ) -> usize {
let id = NEXT_ID.fetch_add(1, Ordering::SeqCst); let id = NEXT_ID.fetch_add(1, Ordering::SeqCst);
let origin = state.borrow::<ModuleSpecifier>().to_string(); let origin = state.borrow::<ModuleSpecifier>().to_string();
let description = TestStepDescription { let description = TestStepDescription {
@ -169,7 +169,7 @@ fn op_register_test_step(
}; };
let sender = state.borrow_mut::<TestEventSender>(); let sender = state.borrow_mut::<TestEventSender>();
sender.send(TestEvent::StepRegister(description)).ok(); sender.send(TestEvent::StepRegister(description)).ok();
Ok(id) id
} }
#[op2(fast)] #[op2(fast)]

View file

@ -4,9 +4,6 @@ use aes::cipher::block_padding::Pkcs7;
use aes::cipher::BlockDecryptMut; use aes::cipher::BlockDecryptMut;
use aes::cipher::BlockEncryptMut; use aes::cipher::BlockEncryptMut;
use aes::cipher::KeyIvInit; use aes::cipher::KeyIvInit;
use deno_core::error::range_error;
use deno_core::error::type_error;
use deno_core::error::AnyError;
use deno_core::Resource; use deno_core::Resource;
use digest::generic_array::GenericArray; use digest::generic_array::GenericArray;
use digest::KeyInit; use digest::KeyInit;
@ -50,8 +47,22 @@ pub struct DecipherContext {
decipher: Rc<RefCell<Decipher>>, decipher: Rc<RefCell<Decipher>>,
} }
#[derive(Debug, thiserror::Error)]
pub enum CipherContextError {
#[error("Cipher context is already in use")]
ContextInUse,
#[error("{0}")]
Resource(deno_core::error::AnyError),
#[error(transparent)]
Cipher(#[from] CipherError),
}
impl CipherContext { impl CipherContext {
pub fn new(algorithm: &str, key: &[u8], iv: &[u8]) -> Result<Self, AnyError> { pub fn new(
algorithm: &str,
key: &[u8],
iv: &[u8],
) -> Result<Self, CipherContextError> {
Ok(Self { Ok(Self {
cipher: Rc::new(RefCell::new(Cipher::new(algorithm, key, iv)?)), cipher: Rc::new(RefCell::new(Cipher::new(algorithm, key, iv)?)),
}) })
@ -74,16 +85,31 @@ impl CipherContext {
auto_pad: bool, auto_pad: bool,
input: &[u8], input: &[u8],
output: &mut [u8], output: &mut [u8],
) -> Result<Tag, AnyError> { ) -> Result<Tag, CipherContextError> {
Rc::try_unwrap(self.cipher) Rc::try_unwrap(self.cipher)
.map_err(|_| type_error("Cipher context is already in use"))? .map_err(|_| CipherContextError::ContextInUse)?
.into_inner() .into_inner()
.r#final(auto_pad, input, output) .r#final(auto_pad, input, output)
.map_err(Into::into)
} }
} }
#[derive(Debug, thiserror::Error)]
pub enum DecipherContextError {
#[error("Decipher context is already in use")]
ContextInUse,
#[error("{0}")]
Resource(deno_core::error::AnyError),
#[error(transparent)]
Decipher(#[from] DecipherError),
}
impl DecipherContext { impl DecipherContext {
pub fn new(algorithm: &str, key: &[u8], iv: &[u8]) -> Result<Self, AnyError> { pub fn new(
algorithm: &str,
key: &[u8],
iv: &[u8],
) -> Result<Self, DecipherContextError> {
Ok(Self { Ok(Self {
decipher: Rc::new(RefCell::new(Decipher::new(algorithm, key, iv)?)), decipher: Rc::new(RefCell::new(Decipher::new(algorithm, key, iv)?)),
}) })
@ -103,11 +129,12 @@ impl DecipherContext {
input: &[u8], input: &[u8],
output: &mut [u8], output: &mut [u8],
auth_tag: &[u8], auth_tag: &[u8],
) -> Result<(), AnyError> { ) -> Result<(), DecipherContextError> {
Rc::try_unwrap(self.decipher) Rc::try_unwrap(self.decipher)
.map_err(|_| type_error("Decipher context is already in use"))? .map_err(|_| DecipherContextError::ContextInUse)?
.into_inner() .into_inner()
.r#final(auto_pad, input, output, auth_tag) .r#final(auto_pad, input, output, auth_tag)
.map_err(Into::into)
} }
} }
@ -123,12 +150,26 @@ impl Resource for DecipherContext {
} }
} }
#[derive(Debug, thiserror::Error)]
pub enum CipherError {
#[error("IV length must be 12 bytes")]
InvalidIvLength,
#[error("Invalid key length")]
InvalidKeyLength,
#[error("Invalid initialization vector")]
InvalidInitializationVector,
#[error("Cannot pad the input data")]
CannotPadInputData,
#[error("Unknown cipher {0}")]
UnknownCipher(String),
}
impl Cipher { impl Cipher {
fn new( fn new(
algorithm_name: &str, algorithm_name: &str,
key: &[u8], key: &[u8],
iv: &[u8], iv: &[u8],
) -> Result<Self, AnyError> { ) -> Result<Self, CipherError> {
use Cipher::*; use Cipher::*;
Ok(match algorithm_name { Ok(match algorithm_name {
"aes-128-cbc" => { "aes-128-cbc" => {
@ -139,7 +180,7 @@ impl Cipher {
"aes-256-ecb" => Aes256Ecb(Box::new(ecb::Encryptor::new(key.into()))), "aes-256-ecb" => Aes256Ecb(Box::new(ecb::Encryptor::new(key.into()))),
"aes-128-gcm" => { "aes-128-gcm" => {
if iv.len() != 12 { if iv.len() != 12 {
return Err(type_error("IV length must be 12 bytes")); return Err(CipherError::InvalidIvLength);
} }
let cipher = let cipher =
@ -149,7 +190,7 @@ impl Cipher {
} }
"aes-256-gcm" => { "aes-256-gcm" => {
if iv.len() != 12 { if iv.len() != 12 {
return Err(type_error("IV length must be 12 bytes")); return Err(CipherError::InvalidIvLength);
} }
let cipher = let cipher =
@ -159,15 +200,15 @@ impl Cipher {
} }
"aes256" | "aes-256-cbc" => { "aes256" | "aes-256-cbc" => {
if key.len() != 32 { if key.len() != 32 {
return Err(range_error("Invalid key length")); return Err(CipherError::InvalidKeyLength);
} }
if iv.len() != 16 { if iv.len() != 16 {
return Err(type_error("Invalid initialization vector")); return Err(CipherError::InvalidInitializationVector);
} }
Aes256Cbc(Box::new(cbc::Encryptor::new(key.into(), iv.into()))) Aes256Cbc(Box::new(cbc::Encryptor::new(key.into(), iv.into())))
} }
_ => return Err(type_error(format!("Unknown cipher {algorithm_name}"))), _ => return Err(CipherError::UnknownCipher(algorithm_name.to_string())),
}) })
} }
@ -235,14 +276,14 @@ impl Cipher {
auto_pad: bool, auto_pad: bool,
input: &[u8], input: &[u8],
output: &mut [u8], output: &mut [u8],
) -> Result<Tag, AnyError> { ) -> Result<Tag, CipherError> {
assert!(input.len() < 16); assert!(input.len() < 16);
use Cipher::*; use Cipher::*;
match (self, auto_pad) { match (self, auto_pad) {
(Aes128Cbc(encryptor), true) => { (Aes128Cbc(encryptor), true) => {
let _ = (*encryptor) let _ = (*encryptor)
.encrypt_padded_b2b_mut::<Pkcs7>(input, output) .encrypt_padded_b2b_mut::<Pkcs7>(input, output)
.map_err(|_| type_error("Cannot pad the input data"))?; .map_err(|_| CipherError::CannotPadInputData)?;
Ok(None) Ok(None)
} }
(Aes128Cbc(mut encryptor), false) => { (Aes128Cbc(mut encryptor), false) => {
@ -255,7 +296,7 @@ impl Cipher {
(Aes128Ecb(encryptor), true) => { (Aes128Ecb(encryptor), true) => {
let _ = (*encryptor) let _ = (*encryptor)
.encrypt_padded_b2b_mut::<Pkcs7>(input, output) .encrypt_padded_b2b_mut::<Pkcs7>(input, output)
.map_err(|_| type_error("Cannot pad the input data"))?; .map_err(|_| CipherError::CannotPadInputData)?;
Ok(None) Ok(None)
} }
(Aes128Ecb(mut encryptor), false) => { (Aes128Ecb(mut encryptor), false) => {
@ -268,7 +309,7 @@ impl Cipher {
(Aes192Ecb(encryptor), true) => { (Aes192Ecb(encryptor), true) => {
let _ = (*encryptor) let _ = (*encryptor)
.encrypt_padded_b2b_mut::<Pkcs7>(input, output) .encrypt_padded_b2b_mut::<Pkcs7>(input, output)
.map_err(|_| type_error("Cannot pad the input data"))?; .map_err(|_| CipherError::CannotPadInputData)?;
Ok(None) Ok(None)
} }
(Aes192Ecb(mut encryptor), false) => { (Aes192Ecb(mut encryptor), false) => {
@ -281,7 +322,7 @@ impl Cipher {
(Aes256Ecb(encryptor), true) => { (Aes256Ecb(encryptor), true) => {
let _ = (*encryptor) let _ = (*encryptor)
.encrypt_padded_b2b_mut::<Pkcs7>(input, output) .encrypt_padded_b2b_mut::<Pkcs7>(input, output)
.map_err(|_| type_error("Cannot pad the input data"))?; .map_err(|_| CipherError::CannotPadInputData)?;
Ok(None) Ok(None)
} }
(Aes256Ecb(mut encryptor), false) => { (Aes256Ecb(mut encryptor), false) => {
@ -296,7 +337,7 @@ impl Cipher {
(Aes256Cbc(encryptor), true) => { (Aes256Cbc(encryptor), true) => {
let _ = (*encryptor) let _ = (*encryptor)
.encrypt_padded_b2b_mut::<Pkcs7>(input, output) .encrypt_padded_b2b_mut::<Pkcs7>(input, output)
.map_err(|_| type_error("Cannot pad the input data"))?; .map_err(|_| CipherError::CannotPadInputData)?;
Ok(None) Ok(None)
} }
(Aes256Cbc(mut encryptor), false) => { (Aes256Cbc(mut encryptor), false) => {
@ -319,12 +360,32 @@ impl Cipher {
} }
} }
#[derive(Debug, thiserror::Error)]
pub enum DecipherError {
#[error("IV length must be 12 bytes")]
InvalidIvLength,
#[error("Invalid key length")]
InvalidKeyLength,
#[error("Invalid initialization vector")]
InvalidInitializationVector,
#[error("Cannot unpad the input data")]
CannotUnpadInputData,
#[error("Failed to authenticate data")]
DataAuthenticationFailed,
#[error("setAutoPadding(false) not supported for Aes128Gcm yet")]
SetAutoPaddingFalseAes128GcmUnsupported,
#[error("setAutoPadding(false) not supported for Aes256Gcm yet")]
SetAutoPaddingFalseAes256GcmUnsupported,
#[error("Unknown cipher {0}")]
UnknownCipher(String),
}
impl Decipher { impl Decipher {
fn new( fn new(
algorithm_name: &str, algorithm_name: &str,
key: &[u8], key: &[u8],
iv: &[u8], iv: &[u8],
) -> Result<Self, AnyError> { ) -> Result<Self, DecipherError> {
use Decipher::*; use Decipher::*;
Ok(match algorithm_name { Ok(match algorithm_name {
"aes-128-cbc" => { "aes-128-cbc" => {
@ -335,7 +396,7 @@ impl Decipher {
"aes-256-ecb" => Aes256Ecb(Box::new(ecb::Decryptor::new(key.into()))), "aes-256-ecb" => Aes256Ecb(Box::new(ecb::Decryptor::new(key.into()))),
"aes-128-gcm" => { "aes-128-gcm" => {
if iv.len() != 12 { if iv.len() != 12 {
return Err(type_error("IV length must be 12 bytes")); return Err(DecipherError::InvalidIvLength);
} }
let decipher = let decipher =
@ -345,7 +406,7 @@ impl Decipher {
} }
"aes-256-gcm" => { "aes-256-gcm" => {
if iv.len() != 12 { if iv.len() != 12 {
return Err(type_error("IV length must be 12 bytes")); return Err(DecipherError::InvalidIvLength);
} }
let decipher = let decipher =
@ -355,15 +416,17 @@ impl Decipher {
} }
"aes256" | "aes-256-cbc" => { "aes256" | "aes-256-cbc" => {
if key.len() != 32 { if key.len() != 32 {
return Err(range_error("Invalid key length")); return Err(DecipherError::InvalidKeyLength);
} }
if iv.len() != 16 { if iv.len() != 16 {
return Err(type_error("Invalid initialization vector")); return Err(DecipherError::InvalidInitializationVector);
} }
Aes256Cbc(Box::new(cbc::Decryptor::new(key.into(), iv.into()))) Aes256Cbc(Box::new(cbc::Decryptor::new(key.into(), iv.into())))
} }
_ => return Err(type_error(format!("Unknown cipher {algorithm_name}"))), _ => {
return Err(DecipherError::UnknownCipher(algorithm_name.to_string()))
}
}) })
} }
@ -432,14 +495,14 @@ impl Decipher {
input: &[u8], input: &[u8],
output: &mut [u8], output: &mut [u8],
auth_tag: &[u8], auth_tag: &[u8],
) -> Result<(), AnyError> { ) -> Result<(), DecipherError> {
use Decipher::*; use Decipher::*;
match (self, auto_pad) { match (self, auto_pad) {
(Aes128Cbc(decryptor), true) => { (Aes128Cbc(decryptor), true) => {
assert!(input.len() == 16); assert!(input.len() == 16);
let _ = (*decryptor) let _ = (*decryptor)
.decrypt_padded_b2b_mut::<Pkcs7>(input, output) .decrypt_padded_b2b_mut::<Pkcs7>(input, output)
.map_err(|_| type_error("Cannot unpad the input data"))?; .map_err(|_| DecipherError::CannotUnpadInputData)?;
Ok(()) Ok(())
} }
(Aes128Cbc(mut decryptor), false) => { (Aes128Cbc(mut decryptor), false) => {
@ -453,7 +516,7 @@ impl Decipher {
assert!(input.len() == 16); assert!(input.len() == 16);
let _ = (*decryptor) let _ = (*decryptor)
.decrypt_padded_b2b_mut::<Pkcs7>(input, output) .decrypt_padded_b2b_mut::<Pkcs7>(input, output)
.map_err(|_| type_error("Cannot unpad the input data"))?; .map_err(|_| DecipherError::CannotUnpadInputData)?;
Ok(()) Ok(())
} }
(Aes128Ecb(mut decryptor), false) => { (Aes128Ecb(mut decryptor), false) => {
@ -467,7 +530,7 @@ impl Decipher {
assert!(input.len() == 16); assert!(input.len() == 16);
let _ = (*decryptor) let _ = (*decryptor)
.decrypt_padded_b2b_mut::<Pkcs7>(input, output) .decrypt_padded_b2b_mut::<Pkcs7>(input, output)
.map_err(|_| type_error("Cannot unpad the input data"))?; .map_err(|_| DecipherError::CannotUnpadInputData)?;
Ok(()) Ok(())
} }
(Aes192Ecb(mut decryptor), false) => { (Aes192Ecb(mut decryptor), false) => {
@ -481,7 +544,7 @@ impl Decipher {
assert!(input.len() == 16); assert!(input.len() == 16);
let _ = (*decryptor) let _ = (*decryptor)
.decrypt_padded_b2b_mut::<Pkcs7>(input, output) .decrypt_padded_b2b_mut::<Pkcs7>(input, output)
.map_err(|_| type_error("Cannot unpad the input data"))?; .map_err(|_| DecipherError::CannotUnpadInputData)?;
Ok(()) Ok(())
} }
(Aes256Ecb(mut decryptor), false) => { (Aes256Ecb(mut decryptor), false) => {
@ -496,28 +559,28 @@ impl Decipher {
if tag.as_slice() == auth_tag { if tag.as_slice() == auth_tag {
Ok(()) Ok(())
} else { } else {
Err(type_error("Failed to authenticate data")) Err(DecipherError::DataAuthenticationFailed)
} }
} }
(Aes128Gcm(_), false) => Err(type_error( (Aes128Gcm(_), false) => {
"setAutoPadding(false) not supported for Aes256Gcm yet", Err(DecipherError::SetAutoPaddingFalseAes128GcmUnsupported)
)), }
(Aes256Gcm(decipher), true) => { (Aes256Gcm(decipher), true) => {
let tag = decipher.finish(); let tag = decipher.finish();
if tag.as_slice() == auth_tag { if tag.as_slice() == auth_tag {
Ok(()) Ok(())
} else { } else {
Err(type_error("Failed to authenticate data")) Err(DecipherError::DataAuthenticationFailed)
} }
} }
(Aes256Gcm(_), false) => Err(type_error( (Aes256Gcm(_), false) => {
"setAutoPadding(false) not supported for Aes256Gcm yet", Err(DecipherError::SetAutoPaddingFalseAes256GcmUnsupported)
)), }
(Aes256Cbc(decryptor), true) => { (Aes256Cbc(decryptor), true) => {
assert!(input.len() == 16); assert!(input.len() == 16);
let _ = (*decryptor) let _ = (*decryptor)
.decrypt_padded_b2b_mut::<Pkcs7>(input, output) .decrypt_padded_b2b_mut::<Pkcs7>(input, output)
.map_err(|_| type_error("Cannot unpad the input data"))?; .map_err(|_| DecipherError::CannotUnpadInputData)?;
Ok(()) Ok(())
} }
(Aes256Cbc(mut decryptor), false) => { (Aes256Cbc(mut decryptor), false) => {

View file

@ -1,6 +1,4 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
use deno_core::error::generic_error;
use deno_core::error::AnyError;
use deno_core::GarbageCollected; use deno_core::GarbageCollected;
use digest::Digest; use digest::Digest;
use digest::DynDigest; use digest::DynDigest;
@ -19,7 +17,7 @@ impl Hasher {
pub fn new( pub fn new(
algorithm: &str, algorithm: &str,
output_length: Option<usize>, output_length: Option<usize>,
) -> Result<Self, AnyError> { ) -> Result<Self, HashError> {
let hash = Hash::new(algorithm, output_length)?; let hash = Hash::new(algorithm, output_length)?;
Ok(Self { Ok(Self {
@ -44,7 +42,7 @@ impl Hasher {
pub fn clone_inner( pub fn clone_inner(
&self, &self,
output_length: Option<usize>, output_length: Option<usize>,
) -> Result<Option<Self>, AnyError> { ) -> Result<Option<Self>, HashError> {
let hash = self.hash.borrow(); let hash = self.hash.borrow();
let Some(hash) = hash.as_ref() else { let Some(hash) = hash.as_ref() else {
return Ok(None); return Ok(None);
@ -184,11 +182,19 @@ pub enum Hash {
use Hash::*; use Hash::*;
#[derive(Debug, thiserror::Error)]
pub enum HashError {
#[error("Output length mismatch for non-extendable algorithm")]
OutputLengthMismatch,
#[error("Digest method not supported: {0}")]
DigestMethodUnsupported(String),
}
impl Hash { impl Hash {
pub fn new( pub fn new(
algorithm_name: &str, algorithm_name: &str,
output_length: Option<usize>, output_length: Option<usize>,
) -> Result<Self, AnyError> { ) -> Result<Self, HashError> {
match algorithm_name { match algorithm_name {
"shake128" => return Ok(Shake128(Default::default(), output_length)), "shake128" => return Ok(Shake128(Default::default(), output_length)),
"shake256" => return Ok(Shake256(Default::default(), output_length)), "shake256" => return Ok(Shake256(Default::default(), output_length)),
@ -201,17 +207,13 @@ impl Hash {
let digest: D = Digest::new(); let digest: D = Digest::new();
if let Some(length) = output_length { if let Some(length) = output_length {
if length != digest.output_size() { if length != digest.output_size() {
return Err(generic_error( return Err(HashError::OutputLengthMismatch);
"Output length mismatch for non-extendable algorithm",
));
} }
} }
FixedSize(Box::new(digest)) FixedSize(Box::new(digest))
}, },
_ => { _ => {
return Err(generic_error(format!( return Err(HashError::DigestMethodUnsupported(algorithm_name.to_string()))
"Digest method not supported: {algorithm_name}"
)))
} }
); );
@ -243,14 +245,12 @@ impl Hash {
pub fn clone_hash( pub fn clone_hash(
&self, &self,
output_length: Option<usize>, output_length: Option<usize>,
) -> Result<Self, AnyError> { ) -> Result<Self, HashError> {
let hash = match self { let hash = match self {
FixedSize(context) => { FixedSize(context) => {
if let Some(length) = output_length { if let Some(length) = output_length {
if length != context.output_size() { if length != context.output_size() {
return Err(generic_error( return Err(HashError::OutputLengthMismatch);
"Output length mismatch for non-extendable algorithm",
));
} }
} }
FixedSize(context.box_clone()) FixedSize(context.box_clone())

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,6 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
use deno_core::error::generic_error; use deno_core::error::generic_error;
use deno_core::error::type_error; use deno_core::error::type_error;
use deno_core::error::AnyError;
use deno_core::op2; use deno_core::op2;
use deno_core::unsync::spawn_blocking; use deno_core::unsync::spawn_blocking;
use deno_core::JsBuffer; use deno_core::JsBuffer;
@ -34,14 +33,14 @@ use rsa::Pkcs1v15Encrypt;
use rsa::RsaPrivateKey; use rsa::RsaPrivateKey;
use rsa::RsaPublicKey; use rsa::RsaPublicKey;
mod cipher; pub mod cipher;
mod dh; mod dh;
mod digest; pub mod digest;
pub mod keys; pub mod keys;
mod md5_sha1; mod md5_sha1;
mod pkcs3; mod pkcs3;
mod primes; mod primes;
mod sign; pub mod sign;
pub mod x509; pub mod x509;
use self::digest::match_fixed_digest_with_eager_block_buffer; use self::digest::match_fixed_digest_with_eager_block_buffer;
@ -58,38 +57,31 @@ pub fn op_node_check_prime(
pub fn op_node_check_prime_bytes( pub fn op_node_check_prime_bytes(
#[anybuffer] bytes: &[u8], #[anybuffer] bytes: &[u8],
#[number] checks: usize, #[number] checks: usize,
) -> Result<bool, AnyError> { ) -> bool {
let candidate = BigInt::from_bytes_be(num_bigint::Sign::Plus, bytes); let candidate = BigInt::from_bytes_be(num_bigint::Sign::Plus, bytes);
Ok(primes::is_probably_prime(&candidate, checks)) primes::is_probably_prime(&candidate, checks)
} }
#[op2(async)] #[op2(async)]
pub async fn op_node_check_prime_async( pub async fn op_node_check_prime_async(
#[bigint] num: i64, #[bigint] num: i64,
#[number] checks: usize, #[number] checks: usize,
) -> Result<bool, AnyError> { ) -> Result<bool, tokio::task::JoinError> {
// TODO(@littledivy): use rayon for CPU-bound tasks // TODO(@littledivy): use rayon for CPU-bound tasks
Ok( spawn_blocking(move || primes::is_probably_prime(&BigInt::from(num), checks))
spawn_blocking(move || { .await
primes::is_probably_prime(&BigInt::from(num), checks)
})
.await?,
)
} }
#[op2(async)] #[op2(async)]
pub fn op_node_check_prime_bytes_async( pub fn op_node_check_prime_bytes_async(
#[anybuffer] bytes: &[u8], #[anybuffer] bytes: &[u8],
#[number] checks: usize, #[number] checks: usize,
) -> Result<impl Future<Output = Result<bool, AnyError>>, AnyError> { ) -> impl Future<Output = Result<bool, tokio::task::JoinError>> {
let candidate = BigInt::from_bytes_be(num_bigint::Sign::Plus, bytes); let candidate = BigInt::from_bytes_be(num_bigint::Sign::Plus, bytes);
// TODO(@littledivy): use rayon for CPU-bound tasks // TODO(@littledivy): use rayon for CPU-bound tasks
Ok(async move { async move {
Ok( spawn_blocking(move || primes::is_probably_prime(&candidate, checks)).await
spawn_blocking(move || primes::is_probably_prime(&candidate, checks)) }
.await?,
)
})
} }
#[op2] #[op2]
@ -97,7 +89,7 @@ pub fn op_node_check_prime_bytes_async(
pub fn op_node_create_hash( pub fn op_node_create_hash(
#[string] algorithm: &str, #[string] algorithm: &str,
output_length: Option<u32>, output_length: Option<u32>,
) -> Result<digest::Hasher, AnyError> { ) -> Result<digest::Hasher, digest::HashError> {
digest::Hasher::new(algorithm, output_length.map(|l| l as usize)) digest::Hasher::new(algorithm, output_length.map(|l| l as usize))
} }
@ -145,17 +137,31 @@ pub fn op_node_hash_digest_hex(
pub fn op_node_hash_clone( pub fn op_node_hash_clone(
#[cppgc] hasher: &digest::Hasher, #[cppgc] hasher: &digest::Hasher,
output_length: Option<u32>, output_length: Option<u32>,
) -> Result<Option<digest::Hasher>, AnyError> { ) -> Result<Option<digest::Hasher>, digest::HashError> {
hasher.clone_inner(output_length.map(|l| l as usize)) hasher.clone_inner(output_length.map(|l| l as usize))
} }
#[derive(Debug, thiserror::Error)]
pub enum PrivateEncryptDecryptError {
#[error(transparent)]
Pkcs8(#[from] pkcs8::Error),
#[error(transparent)]
Spki(#[from] spki::Error),
#[error(transparent)]
Utf8(#[from] std::str::Utf8Error),
#[error(transparent)]
Rsa(#[from] rsa::Error),
#[error("Unknown padding")]
UnknownPadding,
}
#[op2] #[op2]
#[serde] #[serde]
pub fn op_node_private_encrypt( pub fn op_node_private_encrypt(
#[serde] key: StringOrBuffer, #[serde] key: StringOrBuffer,
#[serde] msg: StringOrBuffer, #[serde] msg: StringOrBuffer,
#[smi] padding: u32, #[smi] padding: u32,
) -> Result<ToJsBuffer, AnyError> { ) -> Result<ToJsBuffer, PrivateEncryptDecryptError> {
let key = RsaPrivateKey::from_pkcs8_pem((&key).try_into()?)?; let key = RsaPrivateKey::from_pkcs8_pem((&key).try_into()?)?;
let mut rng = rand::thread_rng(); let mut rng = rand::thread_rng();
@ -172,7 +178,7 @@ pub fn op_node_private_encrypt(
.encrypt(&mut rng, Oaep::new::<sha1::Sha1>(), &msg)? .encrypt(&mut rng, Oaep::new::<sha1::Sha1>(), &msg)?
.into(), .into(),
), ),
_ => Err(type_error("Unknown padding")), _ => Err(PrivateEncryptDecryptError::UnknownPadding),
} }
} }
@ -182,13 +188,13 @@ pub fn op_node_private_decrypt(
#[serde] key: StringOrBuffer, #[serde] key: StringOrBuffer,
#[serde] msg: StringOrBuffer, #[serde] msg: StringOrBuffer,
#[smi] padding: u32, #[smi] padding: u32,
) -> Result<ToJsBuffer, AnyError> { ) -> Result<ToJsBuffer, PrivateEncryptDecryptError> {
let key = RsaPrivateKey::from_pkcs8_pem((&key).try_into()?)?; let key = RsaPrivateKey::from_pkcs8_pem((&key).try_into()?)?;
match padding { match padding {
1 => Ok(key.decrypt(Pkcs1v15Encrypt, &msg)?.into()), 1 => Ok(key.decrypt(Pkcs1v15Encrypt, &msg)?.into()),
4 => Ok(key.decrypt(Oaep::new::<sha1::Sha1>(), &msg)?.into()), 4 => Ok(key.decrypt(Oaep::new::<sha1::Sha1>(), &msg)?.into()),
_ => Err(type_error("Unknown padding")), _ => Err(PrivateEncryptDecryptError::UnknownPadding),
} }
} }
@ -198,7 +204,7 @@ pub fn op_node_public_encrypt(
#[serde] key: StringOrBuffer, #[serde] key: StringOrBuffer,
#[serde] msg: StringOrBuffer, #[serde] msg: StringOrBuffer,
#[smi] padding: u32, #[smi] padding: u32,
) -> Result<ToJsBuffer, AnyError> { ) -> Result<ToJsBuffer, PrivateEncryptDecryptError> {
let key = RsaPublicKey::from_public_key_pem((&key).try_into()?)?; let key = RsaPublicKey::from_public_key_pem((&key).try_into()?)?;
let mut rng = rand::thread_rng(); let mut rng = rand::thread_rng();
@ -209,7 +215,7 @@ pub fn op_node_public_encrypt(
.encrypt(&mut rng, Oaep::new::<sha1::Sha1>(), &msg)? .encrypt(&mut rng, Oaep::new::<sha1::Sha1>(), &msg)?
.into(), .into(),
), ),
_ => Err(type_error("Unknown padding")), _ => Err(PrivateEncryptDecryptError::UnknownPadding),
} }
} }
@ -220,7 +226,7 @@ pub fn op_node_create_cipheriv(
#[string] algorithm: &str, #[string] algorithm: &str,
#[buffer] key: &[u8], #[buffer] key: &[u8],
#[buffer] iv: &[u8], #[buffer] iv: &[u8],
) -> Result<u32, AnyError> { ) -> Result<u32, cipher::CipherContextError> {
let context = cipher::CipherContext::new(algorithm, key, iv)?; let context = cipher::CipherContext::new(algorithm, key, iv)?;
Ok(state.resource_table.add(context)) Ok(state.resource_table.add(context))
} }
@ -262,11 +268,14 @@ pub fn op_node_cipheriv_final(
auto_pad: bool, auto_pad: bool,
#[buffer] input: &[u8], #[buffer] input: &[u8],
#[anybuffer] output: &mut [u8], #[anybuffer] output: &mut [u8],
) -> Result<Option<Vec<u8>>, AnyError> { ) -> Result<Option<Vec<u8>>, cipher::CipherContextError> {
let context = state.resource_table.take::<cipher::CipherContext>(rid)?; let context = state
.resource_table
.take::<cipher::CipherContext>(rid)
.map_err(cipher::CipherContextError::Resource)?;
let context = Rc::try_unwrap(context) let context = Rc::try_unwrap(context)
.map_err(|_| type_error("Cipher context is already in use"))?; .map_err(|_| cipher::CipherContextError::ContextInUse)?;
context.r#final(auto_pad, input, output) context.r#final(auto_pad, input, output).map_err(Into::into)
} }
#[op2] #[op2]
@ -274,10 +283,13 @@ pub fn op_node_cipheriv_final(
pub fn op_node_cipheriv_take( pub fn op_node_cipheriv_take(
state: &mut OpState, state: &mut OpState,
#[smi] rid: u32, #[smi] rid: u32,
) -> Result<Option<Vec<u8>>, AnyError> { ) -> Result<Option<Vec<u8>>, cipher::CipherContextError> {
let context = state.resource_table.take::<cipher::CipherContext>(rid)?; let context = state
.resource_table
.take::<cipher::CipherContext>(rid)
.map_err(cipher::CipherContextError::Resource)?;
let context = Rc::try_unwrap(context) let context = Rc::try_unwrap(context)
.map_err(|_| type_error("Cipher context is already in use"))?; .map_err(|_| cipher::CipherContextError::ContextInUse)?;
Ok(context.take_tag()) Ok(context.take_tag())
} }
@ -288,7 +300,7 @@ pub fn op_node_create_decipheriv(
#[string] algorithm: &str, #[string] algorithm: &str,
#[buffer] key: &[u8], #[buffer] key: &[u8],
#[buffer] iv: &[u8], #[buffer] iv: &[u8],
) -> Result<u32, AnyError> { ) -> Result<u32, cipher::DecipherContextError> {
let context = cipher::DecipherContext::new(algorithm, key, iv)?; let context = cipher::DecipherContext::new(algorithm, key, iv)?;
Ok(state.resource_table.add(context)) Ok(state.resource_table.add(context))
} }
@ -326,10 +338,13 @@ pub fn op_node_decipheriv_decrypt(
pub fn op_node_decipheriv_take( pub fn op_node_decipheriv_take(
state: &mut OpState, state: &mut OpState,
#[smi] rid: u32, #[smi] rid: u32,
) -> Result<(), AnyError> { ) -> Result<(), cipher::DecipherContextError> {
let context = state.resource_table.take::<cipher::DecipherContext>(rid)?; let context = state
.resource_table
.take::<cipher::DecipherContext>(rid)
.map_err(cipher::DecipherContextError::Resource)?;
Rc::try_unwrap(context) Rc::try_unwrap(context)
.map_err(|_| type_error("Cipher context is already in use"))?; .map_err(|_| cipher::DecipherContextError::ContextInUse)?;
Ok(()) Ok(())
} }
@ -341,11 +356,16 @@ pub fn op_node_decipheriv_final(
#[buffer] input: &[u8], #[buffer] input: &[u8],
#[anybuffer] output: &mut [u8], #[anybuffer] output: &mut [u8],
#[buffer] auth_tag: &[u8], #[buffer] auth_tag: &[u8],
) -> Result<(), AnyError> { ) -> Result<(), cipher::DecipherContextError> {
let context = state.resource_table.take::<cipher::DecipherContext>(rid)?; let context = state
.resource_table
.take::<cipher::DecipherContext>(rid)
.map_err(cipher::DecipherContextError::Resource)?;
let context = Rc::try_unwrap(context) let context = Rc::try_unwrap(context)
.map_err(|_| type_error("Cipher context is already in use"))?; .map_err(|_| cipher::DecipherContextError::ContextInUse)?;
context.r#final(auto_pad, input, output, auth_tag) context
.r#final(auto_pad, input, output, auth_tag)
.map_err(Into::into)
} }
#[op2] #[op2]
@ -356,7 +376,7 @@ pub fn op_node_sign(
#[string] digest_type: &str, #[string] digest_type: &str,
#[smi] pss_salt_length: Option<u32>, #[smi] pss_salt_length: Option<u32>,
#[smi] dsa_signature_encoding: u32, #[smi] dsa_signature_encoding: u32,
) -> Result<Box<[u8]>, AnyError> { ) -> Result<Box<[u8]>, sign::KeyObjectHandlePrehashedSignAndVerifyError> {
handle.sign_prehashed( handle.sign_prehashed(
digest_type, digest_type,
digest, digest,
@ -373,7 +393,7 @@ pub fn op_node_verify(
#[buffer] signature: &[u8], #[buffer] signature: &[u8],
#[smi] pss_salt_length: Option<u32>, #[smi] pss_salt_length: Option<u32>,
#[smi] dsa_signature_encoding: u32, #[smi] dsa_signature_encoding: u32,
) -> Result<bool, AnyError> { ) -> Result<bool, sign::KeyObjectHandlePrehashedSignAndVerifyError> {
handle.verify_prehashed( handle.verify_prehashed(
digest_type, digest_type,
digest, digest,
@ -383,13 +403,21 @@ pub fn op_node_verify(
) )
} }
#[derive(Debug, thiserror::Error)]
pub enum Pbkdf2Error {
#[error("unsupported digest: {0}")]
UnsupportedDigest(String),
#[error(transparent)]
Join(#[from] tokio::task::JoinError),
}
fn pbkdf2_sync( fn pbkdf2_sync(
password: &[u8], password: &[u8],
salt: &[u8], salt: &[u8],
iterations: u32, iterations: u32,
algorithm_name: &str, algorithm_name: &str,
derived_key: &mut [u8], derived_key: &mut [u8],
) -> Result<(), AnyError> { ) -> Result<(), Pbkdf2Error> {
match_fixed_digest_with_eager_block_buffer!( match_fixed_digest_with_eager_block_buffer!(
algorithm_name, algorithm_name,
fn <D>() { fn <D>() {
@ -397,10 +425,7 @@ fn pbkdf2_sync(
Ok(()) Ok(())
}, },
_ => { _ => {
Err(type_error(format!( Err(Pbkdf2Error::UnsupportedDigest(algorithm_name.to_string()))
"unsupported digest: {}",
algorithm_name
)))
} }
) )
} }
@ -424,7 +449,7 @@ pub async fn op_node_pbkdf2_async(
#[smi] iterations: u32, #[smi] iterations: u32,
#[string] digest: String, #[string] digest: String,
#[number] keylen: usize, #[number] keylen: usize,
) -> Result<ToJsBuffer, AnyError> { ) -> Result<ToJsBuffer, Pbkdf2Error> {
spawn_blocking(move || { spawn_blocking(move || {
let mut derived_key = vec![0; keylen]; let mut derived_key = vec![0; keylen];
pbkdf2_sync(&password, &salt, iterations, &digest, &mut derived_key) pbkdf2_sync(&password, &salt, iterations, &digest, &mut derived_key)
@ -450,15 +475,27 @@ pub async fn op_node_fill_random_async(#[smi] len: i32) -> ToJsBuffer {
.unwrap() .unwrap()
} }
#[derive(Debug, thiserror::Error)]
pub enum HkdfError {
#[error("expected secret key")]
ExpectedSecretKey,
#[error("HKDF-Expand failed")]
HkdfExpandFailed,
#[error("Unsupported digest: {0}")]
UnsupportedDigest(String),
#[error(transparent)]
Join(#[from] tokio::task::JoinError),
}
fn hkdf_sync( fn hkdf_sync(
digest_algorithm: &str, digest_algorithm: &str,
handle: &KeyObjectHandle, handle: &KeyObjectHandle,
salt: &[u8], salt: &[u8],
info: &[u8], info: &[u8],
okm: &mut [u8], okm: &mut [u8],
) -> Result<(), AnyError> { ) -> Result<(), HkdfError> {
let Some(ikm) = handle.as_secret_key() else { let Some(ikm) = handle.as_secret_key() else {
return Err(type_error("expected secret key")); return Err(HkdfError::ExpectedSecretKey);
}; };
match_fixed_digest_with_eager_block_buffer!( match_fixed_digest_with_eager_block_buffer!(
@ -466,10 +503,10 @@ fn hkdf_sync(
fn <D>() { fn <D>() {
let hk = Hkdf::<D>::new(Some(salt), ikm); let hk = Hkdf::<D>::new(Some(salt), ikm);
hk.expand(info, okm) hk.expand(info, okm)
.map_err(|_| type_error("HKDF-Expand failed")) .map_err(|_| HkdfError::HkdfExpandFailed)
}, },
_ => { _ => {
Err(type_error(format!("Unsupported digest: {}", digest_algorithm))) Err(HkdfError::UnsupportedDigest(digest_algorithm.to_string()))
} }
) )
} }
@ -481,7 +518,7 @@ pub fn op_node_hkdf(
#[buffer] salt: &[u8], #[buffer] salt: &[u8],
#[buffer] info: &[u8], #[buffer] info: &[u8],
#[buffer] okm: &mut [u8], #[buffer] okm: &mut [u8],
) -> Result<(), AnyError> { ) -> Result<(), HkdfError> {
hkdf_sync(digest_algorithm, handle, salt, info, okm) hkdf_sync(digest_algorithm, handle, salt, info, okm)
} }
@ -493,7 +530,7 @@ pub async fn op_node_hkdf_async(
#[buffer] salt: JsBuffer, #[buffer] salt: JsBuffer,
#[buffer] info: JsBuffer, #[buffer] info: JsBuffer,
#[number] okm_len: usize, #[number] okm_len: usize,
) -> Result<ToJsBuffer, AnyError> { ) -> Result<ToJsBuffer, HkdfError> {
let handle = handle.clone(); let handle = handle.clone();
spawn_blocking(move || { spawn_blocking(move || {
let mut okm = vec![0u8; okm_len]; let mut okm = vec![0u8; okm_len];
@ -509,27 +546,24 @@ pub fn op_node_dh_compute_secret(
#[buffer] prime: JsBuffer, #[buffer] prime: JsBuffer,
#[buffer] private_key: JsBuffer, #[buffer] private_key: JsBuffer,
#[buffer] their_public_key: JsBuffer, #[buffer] their_public_key: JsBuffer,
) -> Result<ToJsBuffer, AnyError> { ) -> ToJsBuffer {
let pubkey: BigUint = BigUint::from_bytes_be(their_public_key.as_ref()); let pubkey: BigUint = BigUint::from_bytes_be(their_public_key.as_ref());
let privkey: BigUint = BigUint::from_bytes_be(private_key.as_ref()); let privkey: BigUint = BigUint::from_bytes_be(private_key.as_ref());
let primei: BigUint = BigUint::from_bytes_be(prime.as_ref()); let primei: BigUint = BigUint::from_bytes_be(prime.as_ref());
let shared_secret: BigUint = pubkey.modpow(&privkey, &primei); let shared_secret: BigUint = pubkey.modpow(&privkey, &primei);
Ok(shared_secret.to_bytes_be().into()) shared_secret.to_bytes_be().into()
} }
#[op2(fast)] #[op2(fast)]
#[number] #[number]
pub fn op_node_random_int( pub fn op_node_random_int(#[number] min: i64, #[number] max: i64) -> i64 {
#[number] min: i64,
#[number] max: i64,
) -> Result<i64, AnyError> {
let mut rng = rand::thread_rng(); let mut rng = rand::thread_rng();
// Uniform distribution is required to avoid Modulo Bias // Uniform distribution is required to avoid Modulo Bias
// https://en.wikipedia.org/wiki/FisherYates_shuffle#Modulo_bias // https://en.wikipedia.org/wiki/FisherYates_shuffle#Modulo_bias
let dist = Uniform::from(min..max); let dist = Uniform::from(min..max);
Ok(dist.sample(&mut rng)) dist.sample(&mut rng)
} }
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
@ -542,7 +576,7 @@ fn scrypt(
parallelization: u32, parallelization: u32,
_maxmem: u32, _maxmem: u32,
output_buffer: &mut [u8], output_buffer: &mut [u8],
) -> Result<(), AnyError> { ) -> Result<(), deno_core::error::AnyError> {
// Construct Params // Construct Params
let params = scrypt::Params::new( let params = scrypt::Params::new(
cost as u8, cost as u8,
@ -573,7 +607,7 @@ pub fn op_node_scrypt_sync(
#[smi] parallelization: u32, #[smi] parallelization: u32,
#[smi] maxmem: u32, #[smi] maxmem: u32,
#[anybuffer] output_buffer: &mut [u8], #[anybuffer] output_buffer: &mut [u8],
) -> Result<(), AnyError> { ) -> Result<(), deno_core::error::AnyError> {
scrypt( scrypt(
password, password,
salt, salt,
@ -586,6 +620,14 @@ pub fn op_node_scrypt_sync(
) )
} }
#[derive(Debug, thiserror::Error)]
pub enum ScryptAsyncError {
#[error(transparent)]
Join(#[from] tokio::task::JoinError),
#[error(transparent)]
Other(deno_core::error::AnyError),
}
#[op2(async)] #[op2(async)]
#[serde] #[serde]
pub async fn op_node_scrypt_async( pub async fn op_node_scrypt_async(
@ -596,10 +638,11 @@ pub async fn op_node_scrypt_async(
#[smi] block_size: u32, #[smi] block_size: u32,
#[smi] parallelization: u32, #[smi] parallelization: u32,
#[smi] maxmem: u32, #[smi] maxmem: u32,
) -> Result<ToJsBuffer, AnyError> { ) -> Result<ToJsBuffer, ScryptAsyncError> {
spawn_blocking(move || { spawn_blocking(move || {
let mut output_buffer = vec![0u8; keylen as usize]; let mut output_buffer = vec![0u8; keylen as usize];
let res = scrypt(
scrypt(
password, password,
salt, salt,
keylen, keylen,
@ -608,25 +651,30 @@ pub async fn op_node_scrypt_async(
parallelization, parallelization,
maxmem, maxmem,
&mut output_buffer, &mut output_buffer,
); )
.map(|_| output_buffer.into())
if res.is_ok() { .map_err(ScryptAsyncError::Other)
Ok(output_buffer.into())
} else {
// TODO(lev): rethrow the error?
Err(generic_error("scrypt failure"))
}
}) })
.await? .await?
} }
#[derive(Debug, thiserror::Error)]
pub enum EcdhEncodePubKey {
#[error("Invalid public key")]
InvalidPublicKey,
#[error("Unsupported curve")]
UnsupportedCurve,
#[error(transparent)]
Sec1(#[from] sec1::Error),
}
#[op2] #[op2]
#[buffer] #[buffer]
pub fn op_node_ecdh_encode_pubkey( pub fn op_node_ecdh_encode_pubkey(
#[string] curve: &str, #[string] curve: &str,
#[buffer] pubkey: &[u8], #[buffer] pubkey: &[u8],
compress: bool, compress: bool,
) -> Result<Vec<u8>, AnyError> { ) -> Result<Vec<u8>, EcdhEncodePubKey> {
use elliptic_curve::sec1::FromEncodedPoint; use elliptic_curve::sec1::FromEncodedPoint;
match curve { match curve {
@ -639,7 +687,7 @@ pub fn op_node_ecdh_encode_pubkey(
); );
// CtOption does not expose its variants. // CtOption does not expose its variants.
if pubkey.is_none().into() { if pubkey.is_none().into() {
return Err(type_error("Invalid public key")); return Err(EcdhEncodePubKey::InvalidPublicKey);
} }
let pubkey = pubkey.unwrap(); let pubkey = pubkey.unwrap();
@ -652,7 +700,7 @@ pub fn op_node_ecdh_encode_pubkey(
); );
// CtOption does not expose its variants. // CtOption does not expose its variants.
if pubkey.is_none().into() { if pubkey.is_none().into() {
return Err(type_error("Invalid public key")); return Err(EcdhEncodePubKey::InvalidPublicKey);
} }
let pubkey = pubkey.unwrap(); let pubkey = pubkey.unwrap();
@ -665,7 +713,7 @@ pub fn op_node_ecdh_encode_pubkey(
); );
// CtOption does not expose its variants. // CtOption does not expose its variants.
if pubkey.is_none().into() { if pubkey.is_none().into() {
return Err(type_error("Invalid public key")); return Err(EcdhEncodePubKey::InvalidPublicKey);
} }
let pubkey = pubkey.unwrap(); let pubkey = pubkey.unwrap();
@ -678,14 +726,14 @@ pub fn op_node_ecdh_encode_pubkey(
); );
// CtOption does not expose its variants. // CtOption does not expose its variants.
if pubkey.is_none().into() { if pubkey.is_none().into() {
return Err(type_error("Invalid public key")); return Err(EcdhEncodePubKey::InvalidPublicKey);
} }
let pubkey = pubkey.unwrap(); let pubkey = pubkey.unwrap();
Ok(pubkey.to_encoded_point(compress).as_ref().to_vec()) Ok(pubkey.to_encoded_point(compress).as_ref().to_vec())
} }
&_ => Err(type_error("Unsupported curve")), &_ => Err(EcdhEncodePubKey::UnsupportedCurve),
} }
} }
@ -695,7 +743,7 @@ pub fn op_node_ecdh_generate_keys(
#[buffer] pubbuf: &mut [u8], #[buffer] pubbuf: &mut [u8],
#[buffer] privbuf: &mut [u8], #[buffer] privbuf: &mut [u8],
#[string] format: &str, #[string] format: &str,
) -> Result<(), AnyError> { ) -> Result<(), deno_core::error::AnyError> {
let mut rng = rand::thread_rng(); let mut rng = rand::thread_rng();
let compress = format == "compressed"; let compress = format == "compressed";
match curve { match curve {
@ -742,7 +790,7 @@ pub fn op_node_ecdh_compute_secret(
#[buffer] this_priv: Option<JsBuffer>, #[buffer] this_priv: Option<JsBuffer>,
#[buffer] their_pub: &mut [u8], #[buffer] their_pub: &mut [u8],
#[buffer] secret: &mut [u8], #[buffer] secret: &mut [u8],
) -> Result<(), AnyError> { ) {
match curve { match curve {
"secp256k1" => { "secp256k1" => {
let their_public_key = let their_public_key =
@ -760,8 +808,6 @@ pub fn op_node_ecdh_compute_secret(
their_public_key.as_affine(), their_public_key.as_affine(),
); );
secret.copy_from_slice(shared_secret.raw_secret_bytes()); secret.copy_from_slice(shared_secret.raw_secret_bytes());
Ok(())
} }
"prime256v1" | "secp256r1" => { "prime256v1" | "secp256r1" => {
let their_public_key = let their_public_key =
@ -776,8 +822,6 @@ pub fn op_node_ecdh_compute_secret(
their_public_key.as_affine(), their_public_key.as_affine(),
); );
secret.copy_from_slice(shared_secret.raw_secret_bytes()); secret.copy_from_slice(shared_secret.raw_secret_bytes());
Ok(())
} }
"secp384r1" => { "secp384r1" => {
let their_public_key = let their_public_key =
@ -792,8 +836,6 @@ pub fn op_node_ecdh_compute_secret(
their_public_key.as_affine(), their_public_key.as_affine(),
); );
secret.copy_from_slice(shared_secret.raw_secret_bytes()); secret.copy_from_slice(shared_secret.raw_secret_bytes());
Ok(())
} }
"secp224r1" => { "secp224r1" => {
let their_public_key = let their_public_key =
@ -808,8 +850,6 @@ pub fn op_node_ecdh_compute_secret(
their_public_key.as_affine(), their_public_key.as_affine(),
); );
secret.copy_from_slice(shared_secret.raw_secret_bytes()); secret.copy_from_slice(shared_secret.raw_secret_bytes());
Ok(())
} }
&_ => todo!(), &_ => todo!(),
} }
@ -820,7 +860,7 @@ pub fn op_node_ecdh_compute_public_key(
#[string] curve: &str, #[string] curve: &str,
#[buffer] privkey: &[u8], #[buffer] privkey: &[u8],
#[buffer] pubkey: &mut [u8], #[buffer] pubkey: &mut [u8],
) -> Result<(), AnyError> { ) {
match curve { match curve {
"secp256k1" => { "secp256k1" => {
let this_private_key = let this_private_key =
@ -828,8 +868,6 @@ pub fn op_node_ecdh_compute_public_key(
.expect("bad private key"); .expect("bad private key");
let public_key = this_private_key.public_key(); let public_key = this_private_key.public_key();
pubkey.copy_from_slice(public_key.to_sec1_bytes().as_ref()); pubkey.copy_from_slice(public_key.to_sec1_bytes().as_ref());
Ok(())
} }
"prime256v1" | "secp256r1" => { "prime256v1" | "secp256r1" => {
let this_private_key = let this_private_key =
@ -837,7 +875,6 @@ pub fn op_node_ecdh_compute_public_key(
.expect("bad private key"); .expect("bad private key");
let public_key = this_private_key.public_key(); let public_key = this_private_key.public_key();
pubkey.copy_from_slice(public_key.to_sec1_bytes().as_ref()); pubkey.copy_from_slice(public_key.to_sec1_bytes().as_ref());
Ok(())
} }
"secp384r1" => { "secp384r1" => {
let this_private_key = let this_private_key =
@ -845,7 +882,6 @@ pub fn op_node_ecdh_compute_public_key(
.expect("bad private key"); .expect("bad private key");
let public_key = this_private_key.public_key(); let public_key = this_private_key.public_key();
pubkey.copy_from_slice(public_key.to_sec1_bytes().as_ref()); pubkey.copy_from_slice(public_key.to_sec1_bytes().as_ref());
Ok(())
} }
"secp224r1" => { "secp224r1" => {
let this_private_key = let this_private_key =
@ -853,7 +889,6 @@ pub fn op_node_ecdh_compute_public_key(
.expect("bad private key"); .expect("bad private key");
let public_key = this_private_key.public_key(); let public_key = this_private_key.public_key();
pubkey.copy_from_slice(public_key.to_sec1_bytes().as_ref()); pubkey.copy_from_slice(public_key.to_sec1_bytes().as_ref());
Ok(())
} }
&_ => todo!(), &_ => todo!(),
} }
@ -874,8 +909,20 @@ pub fn op_node_gen_prime(#[number] size: usize) -> ToJsBuffer {
#[serde] #[serde]
pub async fn op_node_gen_prime_async( pub async fn op_node_gen_prime_async(
#[number] size: usize, #[number] size: usize,
) -> Result<ToJsBuffer, AnyError> { ) -> Result<ToJsBuffer, tokio::task::JoinError> {
Ok(spawn_blocking(move || gen_prime(size)).await?) spawn_blocking(move || gen_prime(size)).await
}
#[derive(Debug, thiserror::Error)]
pub enum DiffieHellmanError {
#[error("Expected private key")]
ExpectedPrivateKey,
#[error("Expected public key")]
ExpectedPublicKey,
#[error("DH parameters mismatch")]
DhParametersMismatch,
#[error("Unsupported key type for diffie hellman, or key type mismatch")]
UnsupportedKeyTypeForDiffieHellmanOrKeyTypeMismatch,
} }
#[op2] #[op2]
@ -883,117 +930,134 @@ pub async fn op_node_gen_prime_async(
pub fn op_node_diffie_hellman( pub fn op_node_diffie_hellman(
#[cppgc] private: &KeyObjectHandle, #[cppgc] private: &KeyObjectHandle,
#[cppgc] public: &KeyObjectHandle, #[cppgc] public: &KeyObjectHandle,
) -> Result<Box<[u8]>, AnyError> { ) -> Result<Box<[u8]>, DiffieHellmanError> {
let private = private let private = private
.as_private_key() .as_private_key()
.ok_or_else(|| type_error("Expected private key"))?; .ok_or(DiffieHellmanError::ExpectedPrivateKey)?;
let public = public let public = public
.as_public_key() .as_public_key()
.ok_or_else(|| type_error("Expected public key"))?; .ok_or(DiffieHellmanError::ExpectedPublicKey)?;
let res = match (private, &*public) { let res =
( match (private, &*public) {
AsymmetricPrivateKey::Ec(EcPrivateKey::P224(private)), (
AsymmetricPublicKey::Ec(EcPublicKey::P224(public)), AsymmetricPrivateKey::Ec(EcPrivateKey::P224(private)),
) => p224::ecdh::diffie_hellman( AsymmetricPublicKey::Ec(EcPublicKey::P224(public)),
private.to_nonzero_scalar(), ) => p224::ecdh::diffie_hellman(
public.as_affine(), private.to_nonzero_scalar(),
) public.as_affine(),
.raw_secret_bytes() )
.to_vec() .raw_secret_bytes()
.into_boxed_slice(), .to_vec()
( .into_boxed_slice(),
AsymmetricPrivateKey::Ec(EcPrivateKey::P256(private)), (
AsymmetricPublicKey::Ec(EcPublicKey::P256(public)), AsymmetricPrivateKey::Ec(EcPrivateKey::P256(private)),
) => p256::ecdh::diffie_hellman( AsymmetricPublicKey::Ec(EcPublicKey::P256(public)),
private.to_nonzero_scalar(), ) => p256::ecdh::diffie_hellman(
public.as_affine(), private.to_nonzero_scalar(),
) public.as_affine(),
.raw_secret_bytes() )
.to_vec() .raw_secret_bytes()
.into_boxed_slice(), .to_vec()
( .into_boxed_slice(),
AsymmetricPrivateKey::Ec(EcPrivateKey::P384(private)), (
AsymmetricPublicKey::Ec(EcPublicKey::P384(public)), AsymmetricPrivateKey::Ec(EcPrivateKey::P384(private)),
) => p384::ecdh::diffie_hellman( AsymmetricPublicKey::Ec(EcPublicKey::P384(public)),
private.to_nonzero_scalar(), ) => p384::ecdh::diffie_hellman(
public.as_affine(), private.to_nonzero_scalar(),
) public.as_affine(),
.raw_secret_bytes() )
.to_vec() .raw_secret_bytes()
.into_boxed_slice(), .to_vec()
( .into_boxed_slice(),
AsymmetricPrivateKey::X25519(private), (
AsymmetricPublicKey::X25519(public), AsymmetricPrivateKey::X25519(private),
) => private AsymmetricPublicKey::X25519(public),
.diffie_hellman(public) ) => private
.to_bytes() .diffie_hellman(public)
.into_iter() .to_bytes()
.collect(), .into_iter()
(AsymmetricPrivateKey::Dh(private), AsymmetricPublicKey::Dh(public)) => { .collect(),
if private.params.prime != public.params.prime (AsymmetricPrivateKey::Dh(private), AsymmetricPublicKey::Dh(public)) => {
|| private.params.base != public.params.base if private.params.prime != public.params.prime
{ || private.params.base != public.params.base
return Err(type_error("DH parameters mismatch")); {
return Err(DiffieHellmanError::DhParametersMismatch);
}
// OSIP - Octet-String-to-Integer primitive
let public_key = public.key.clone().into_vec();
let pubkey = BigUint::from_bytes_be(&public_key);
// Exponentiation (z = y^x mod p)
let prime = BigUint::from_bytes_be(private.params.prime.as_bytes());
let private_key = private.key.clone().into_vec();
let private_key = BigUint::from_bytes_be(&private_key);
let shared_secret = pubkey.modpow(&private_key, &prime);
shared_secret.to_bytes_be().into()
} }
_ => return Err(
// OSIP - Octet-String-to-Integer primitive DiffieHellmanError::UnsupportedKeyTypeForDiffieHellmanOrKeyTypeMismatch,
let public_key = public.key.clone().into_vec(); ),
let pubkey = BigUint::from_bytes_be(&public_key); };
// Exponentiation (z = y^x mod p)
let prime = BigUint::from_bytes_be(private.params.prime.as_bytes());
let private_key = private.key.clone().into_vec();
let private_key = BigUint::from_bytes_be(&private_key);
let shared_secret = pubkey.modpow(&private_key, &prime);
shared_secret.to_bytes_be().into()
}
_ => {
return Err(type_error(
"Unsupported key type for diffie hellman, or key type mismatch",
))
}
};
Ok(res) Ok(res)
} }
#[derive(Debug, thiserror::Error)]
pub enum SignEd25519Error {
#[error("Expected private key")]
ExpectedPrivateKey,
#[error("Expected Ed25519 private key")]
ExpectedEd25519PrivateKey,
#[error("Invalid Ed25519 private key")]
InvalidEd25519PrivateKey,
}
#[op2(fast)] #[op2(fast)]
pub fn op_node_sign_ed25519( pub fn op_node_sign_ed25519(
#[cppgc] key: &KeyObjectHandle, #[cppgc] key: &KeyObjectHandle,
#[buffer] data: &[u8], #[buffer] data: &[u8],
#[buffer] signature: &mut [u8], #[buffer] signature: &mut [u8],
) -> Result<(), AnyError> { ) -> Result<(), SignEd25519Error> {
let private = key let private = key
.as_private_key() .as_private_key()
.ok_or_else(|| type_error("Expected private key"))?; .ok_or(SignEd25519Error::ExpectedPrivateKey)?;
let ed25519 = match private { let ed25519 = match private {
AsymmetricPrivateKey::Ed25519(private) => private, AsymmetricPrivateKey::Ed25519(private) => private,
_ => return Err(type_error("Expected Ed25519 private key")), _ => return Err(SignEd25519Error::ExpectedEd25519PrivateKey),
}; };
let pair = Ed25519KeyPair::from_seed_unchecked(ed25519.as_bytes().as_slice()) let pair = Ed25519KeyPair::from_seed_unchecked(ed25519.as_bytes().as_slice())
.map_err(|_| type_error("Invalid Ed25519 private key"))?; .map_err(|_| SignEd25519Error::InvalidEd25519PrivateKey)?;
signature.copy_from_slice(pair.sign(data).as_ref()); signature.copy_from_slice(pair.sign(data).as_ref());
Ok(()) Ok(())
} }
#[derive(Debug, thiserror::Error)]
pub enum VerifyEd25519Error {
#[error("Expected public key")]
ExpectedPublicKey,
#[error("Expected Ed25519 public key")]
ExpectedEd25519PublicKey,
}
#[op2(fast)] #[op2(fast)]
pub fn op_node_verify_ed25519( pub fn op_node_verify_ed25519(
#[cppgc] key: &KeyObjectHandle, #[cppgc] key: &KeyObjectHandle,
#[buffer] data: &[u8], #[buffer] data: &[u8],
#[buffer] signature: &[u8], #[buffer] signature: &[u8],
) -> Result<bool, AnyError> { ) -> Result<bool, VerifyEd25519Error> {
let public = key let public = key
.as_public_key() .as_public_key()
.ok_or_else(|| type_error("Expected public key"))?; .ok_or(VerifyEd25519Error::ExpectedPublicKey)?;
let ed25519 = match &*public { let ed25519 = match &*public {
AsymmetricPublicKey::Ed25519(public) => public, AsymmetricPublicKey::Ed25519(public) => public,
_ => return Err(type_error("Expected Ed25519 public key")), _ => return Err(VerifyEd25519Error::ExpectedEd25519PublicKey),
}; };
let verified = ring::signature::UnparsedPublicKey::new( let verified = ring::signature::UnparsedPublicKey::new(

View file

@ -1,7 +1,4 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
use deno_core::error::generic_error;
use deno_core::error::type_error;
use deno_core::error::AnyError;
use rand::rngs::OsRng; use rand::rngs::OsRng;
use rsa::signature::hazmat::PrehashSigner as _; use rsa::signature::hazmat::PrehashSigner as _;
use rsa::signature::hazmat::PrehashVerifier as _; use rsa::signature::hazmat::PrehashVerifier as _;
@ -26,7 +23,7 @@ use elliptic_curve::FieldBytesSize;
fn dsa_signature<C: elliptic_curve::PrimeCurve>( fn dsa_signature<C: elliptic_curve::PrimeCurve>(
encoding: u32, encoding: u32,
signature: ecdsa::Signature<C>, signature: ecdsa::Signature<C>,
) -> Result<Box<[u8]>, AnyError> ) -> Result<Box<[u8]>, KeyObjectHandlePrehashedSignAndVerifyError>
where where
MaxSize<C>: ArrayLength<u8>, MaxSize<C>: ArrayLength<u8>,
<FieldBytesSize<C> as Add>::Output: Add<MaxOverhead> + ArrayLength<u8>, <FieldBytesSize<C> as Add>::Output: Add<MaxOverhead> + ArrayLength<u8>,
@ -36,10 +33,54 @@ where
0 => Ok(signature.to_der().to_bytes().to_vec().into_boxed_slice()), 0 => Ok(signature.to_der().to_bytes().to_vec().into_boxed_slice()),
// IEEE P1363 // IEEE P1363
1 => Ok(signature.to_bytes().to_vec().into_boxed_slice()), 1 => Ok(signature.to_bytes().to_vec().into_boxed_slice()),
_ => Err(type_error("invalid DSA signature encoding")), _ => Err(
KeyObjectHandlePrehashedSignAndVerifyError::InvalidDsaSignatureEncoding,
),
} }
} }
#[derive(Debug, thiserror::Error)]
pub enum KeyObjectHandlePrehashedSignAndVerifyError {
#[error("invalid DSA signature encoding")]
InvalidDsaSignatureEncoding,
#[error("key is not a private key")]
KeyIsNotPrivate,
#[error("digest not allowed for RSA signature: {0}")]
DigestNotAllowedForRsaSignature(String),
#[error("failed to sign digest with RSA")]
FailedToSignDigestWithRsa,
#[error("digest not allowed for RSA-PSS signature: {0}")]
DigestNotAllowedForRsaPssSignature(String),
#[error("failed to sign digest with RSA-PSS")]
FailedToSignDigestWithRsaPss,
#[error("failed to sign digest with DSA")]
FailedToSignDigestWithDsa,
#[error("rsa-pss with different mf1 hash algorithm and hash algorithm is not supported")]
RsaPssHashAlgorithmUnsupported,
#[error(
"private key does not allow {actual} to be used, expected {expected}"
)]
PrivateKeyDisallowsUsage { actual: String, expected: String },
#[error("failed to sign digest")]
FailedToSignDigest,
#[error("x25519 key cannot be used for signing")]
X25519KeyCannotBeUsedForSigning,
#[error("Ed25519 key cannot be used for prehashed signing")]
Ed25519KeyCannotBeUsedForPrehashedSigning,
#[error("DH key cannot be used for signing")]
DhKeyCannotBeUsedForSigning,
#[error("key is not a public or private key")]
KeyIsNotPublicOrPrivate,
#[error("Invalid DSA signature")]
InvalidDsaSignature,
#[error("x25519 key cannot be used for verification")]
X25519KeyCannotBeUsedForVerification,
#[error("Ed25519 key cannot be used for prehashed verification")]
Ed25519KeyCannotBeUsedForPrehashedVerification,
#[error("DH key cannot be used for verification")]
DhKeyCannotBeUsedForVerification,
}
impl KeyObjectHandle { impl KeyObjectHandle {
pub fn sign_prehashed( pub fn sign_prehashed(
&self, &self,
@ -47,10 +88,10 @@ impl KeyObjectHandle {
digest: &[u8], digest: &[u8],
pss_salt_length: Option<u32>, pss_salt_length: Option<u32>,
dsa_signature_encoding: u32, dsa_signature_encoding: u32,
) -> Result<Box<[u8]>, AnyError> { ) -> Result<Box<[u8]>, KeyObjectHandlePrehashedSignAndVerifyError> {
let private_key = self let private_key = self
.as_private_key() .as_private_key()
.ok_or_else(|| type_error("key is not a private key"))?; .ok_or(KeyObjectHandlePrehashedSignAndVerifyError::KeyIsNotPrivate)?;
match private_key { match private_key {
AsymmetricPrivateKey::Rsa(key) => { AsymmetricPrivateKey::Rsa(key) => {
@ -63,17 +104,14 @@ impl KeyObjectHandle {
rsa::pkcs1v15::Pkcs1v15Sign::new::<D>() rsa::pkcs1v15::Pkcs1v15Sign::new::<D>()
}, },
_ => { _ => {
return Err(type_error(format!( return Err(KeyObjectHandlePrehashedSignAndVerifyError::DigestNotAllowedForRsaSignature(digest_type.to_string()))
"digest not allowed for RSA signature: {}",
digest_type
)))
} }
) )
}; };
let signature = signer let signature = signer
.sign(Some(&mut OsRng), key, digest) .sign(Some(&mut OsRng), key, digest)
.map_err(|_| generic_error("failed to sign digest with RSA"))?; .map_err(|_| KeyObjectHandlePrehashedSignAndVerifyError::FailedToSignDigestWithRsa)?;
Ok(signature.into()) Ok(signature.into())
} }
AsymmetricPrivateKey::RsaPss(key) => { AsymmetricPrivateKey::RsaPss(key) => {
@ -81,9 +119,7 @@ impl KeyObjectHandle {
let mut salt_length = None; let mut salt_length = None;
if let Some(details) = &key.details { if let Some(details) = &key.details {
if details.hash_algorithm != details.mf1_hash_algorithm { if details.hash_algorithm != details.mf1_hash_algorithm {
return Err(type_error( return Err(KeyObjectHandlePrehashedSignAndVerifyError::RsaPssHashAlgorithmUnsupported);
"rsa-pss with different mf1 hash algorithm and hash algorithm is not supported",
));
} }
hash_algorithm = Some(details.hash_algorithm); hash_algorithm = Some(details.hash_algorithm);
salt_length = Some(details.salt_length as usize); salt_length = Some(details.salt_length as usize);
@ -96,10 +132,10 @@ impl KeyObjectHandle {
fn <D>(algorithm: Option<RsaPssHashAlgorithm>) { fn <D>(algorithm: Option<RsaPssHashAlgorithm>) {
if let Some(hash_algorithm) = hash_algorithm.take() { if let Some(hash_algorithm) = hash_algorithm.take() {
if Some(hash_algorithm) != algorithm { if Some(hash_algorithm) != algorithm {
return Err(type_error(format!( return Err(KeyObjectHandlePrehashedSignAndVerifyError::PrivateKeyDisallowsUsage {
"private key does not allow {} to be used, expected {}", actual: digest_type.to_string(),
digest_type, hash_algorithm.as_str() expected: hash_algorithm.as_str().to_string(),
))); });
} }
} }
if let Some(salt_length) = salt_length { if let Some(salt_length) = salt_length {
@ -109,15 +145,12 @@ impl KeyObjectHandle {
} }
}, },
_ => { _ => {
return Err(type_error(format!( return Err(KeyObjectHandlePrehashedSignAndVerifyError::DigestNotAllowedForRsaPssSignature(digest_type.to_string()));
"digest not allowed for RSA-PSS signature: {}",
digest_type
)))
} }
); );
let signature = pss let signature = pss
.sign(Some(&mut OsRng), &key.key, digest) .sign(Some(&mut OsRng), &key.key, digest)
.map_err(|_| generic_error("failed to sign digest with RSA-PSS"))?; .map_err(|_| KeyObjectHandlePrehashedSignAndVerifyError::FailedToSignDigestWithRsaPss)?;
Ok(signature.into()) Ok(signature.into())
} }
AsymmetricPrivateKey::Dsa(key) => { AsymmetricPrivateKey::Dsa(key) => {
@ -127,15 +160,12 @@ impl KeyObjectHandle {
key.sign_prehashed_rfc6979::<D>(digest) key.sign_prehashed_rfc6979::<D>(digest)
}, },
_ => { _ => {
return Err(type_error(format!( return Err(KeyObjectHandlePrehashedSignAndVerifyError::DigestNotAllowedForRsaSignature(digest_type.to_string()))
"digest not allowed for RSA signature: {}",
digest_type
)))
} }
); );
let signature = let signature =
res.map_err(|_| generic_error("failed to sign digest with DSA"))?; res.map_err(|_| KeyObjectHandlePrehashedSignAndVerifyError::FailedToSignDigestWithDsa)?;
Ok(signature.into()) Ok(signature.into())
} }
AsymmetricPrivateKey::Ec(key) => match key { AsymmetricPrivateKey::Ec(key) => match key {
@ -143,7 +173,7 @@ impl KeyObjectHandle {
let signing_key = p224::ecdsa::SigningKey::from(key); let signing_key = p224::ecdsa::SigningKey::from(key);
let signature: p224::ecdsa::Signature = signing_key let signature: p224::ecdsa::Signature = signing_key
.sign_prehash(digest) .sign_prehash(digest)
.map_err(|_| type_error("failed to sign digest"))?; .map_err(|_| KeyObjectHandlePrehashedSignAndVerifyError::FailedToSignDigest)?;
dsa_signature(dsa_signature_encoding, signature) dsa_signature(dsa_signature_encoding, signature)
} }
@ -151,7 +181,7 @@ impl KeyObjectHandle {
let signing_key = p256::ecdsa::SigningKey::from(key); let signing_key = p256::ecdsa::SigningKey::from(key);
let signature: p256::ecdsa::Signature = signing_key let signature: p256::ecdsa::Signature = signing_key
.sign_prehash(digest) .sign_prehash(digest)
.map_err(|_| type_error("failed to sign digest"))?; .map_err(|_| KeyObjectHandlePrehashedSignAndVerifyError::FailedToSignDigest)?;
dsa_signature(dsa_signature_encoding, signature) dsa_signature(dsa_signature_encoding, signature)
} }
@ -159,19 +189,17 @@ impl KeyObjectHandle {
let signing_key = p384::ecdsa::SigningKey::from(key); let signing_key = p384::ecdsa::SigningKey::from(key);
let signature: p384::ecdsa::Signature = signing_key let signature: p384::ecdsa::Signature = signing_key
.sign_prehash(digest) .sign_prehash(digest)
.map_err(|_| type_error("failed to sign digest"))?; .map_err(|_| KeyObjectHandlePrehashedSignAndVerifyError::FailedToSignDigest)?;
dsa_signature(dsa_signature_encoding, signature) dsa_signature(dsa_signature_encoding, signature)
} }
}, },
AsymmetricPrivateKey::X25519(_) => { AsymmetricPrivateKey::X25519(_) => {
Err(type_error("x25519 key cannot be used for signing")) Err(KeyObjectHandlePrehashedSignAndVerifyError::X25519KeyCannotBeUsedForSigning)
} }
AsymmetricPrivateKey::Ed25519(_) => Err(type_error( AsymmetricPrivateKey::Ed25519(_) => Err(KeyObjectHandlePrehashedSignAndVerifyError::Ed25519KeyCannotBeUsedForPrehashedSigning),
"Ed25519 key cannot be used for prehashed signing",
)),
AsymmetricPrivateKey::Dh(_) => { AsymmetricPrivateKey::Dh(_) => {
Err(type_error("DH key cannot be used for signing")) Err(KeyObjectHandlePrehashedSignAndVerifyError::DhKeyCannotBeUsedForSigning)
} }
} }
} }
@ -183,10 +211,10 @@ impl KeyObjectHandle {
signature: &[u8], signature: &[u8],
pss_salt_length: Option<u32>, pss_salt_length: Option<u32>,
dsa_signature_encoding: u32, dsa_signature_encoding: u32,
) -> Result<bool, AnyError> { ) -> Result<bool, KeyObjectHandlePrehashedSignAndVerifyError> {
let public_key = self let public_key = self.as_public_key().ok_or(
.as_public_key() KeyObjectHandlePrehashedSignAndVerifyError::KeyIsNotPublicOrPrivate,
.ok_or_else(|| type_error("key is not a public or private key"))?; )?;
match &*public_key { match &*public_key {
AsymmetricPublicKey::Rsa(key) => { AsymmetricPublicKey::Rsa(key) => {
@ -199,10 +227,7 @@ impl KeyObjectHandle {
rsa::pkcs1v15::Pkcs1v15Sign::new::<D>() rsa::pkcs1v15::Pkcs1v15Sign::new::<D>()
}, },
_ => { _ => {
return Err(type_error(format!( return Err(KeyObjectHandlePrehashedSignAndVerifyError::DigestNotAllowedForRsaSignature(digest_type.to_string()))
"digest not allowed for RSA signature: {}",
digest_type
)))
} }
) )
}; };
@ -214,9 +239,7 @@ impl KeyObjectHandle {
let mut salt_length = None; let mut salt_length = None;
if let Some(details) = &key.details { if let Some(details) = &key.details {
if details.hash_algorithm != details.mf1_hash_algorithm { if details.hash_algorithm != details.mf1_hash_algorithm {
return Err(type_error( return Err(KeyObjectHandlePrehashedSignAndVerifyError::RsaPssHashAlgorithmUnsupported);
"rsa-pss with different mf1 hash algorithm and hash algorithm is not supported",
));
} }
hash_algorithm = Some(details.hash_algorithm); hash_algorithm = Some(details.hash_algorithm);
salt_length = Some(details.salt_length as usize); salt_length = Some(details.salt_length as usize);
@ -229,10 +252,10 @@ impl KeyObjectHandle {
fn <D>(algorithm: Option<RsaPssHashAlgorithm>) { fn <D>(algorithm: Option<RsaPssHashAlgorithm>) {
if let Some(hash_algorithm) = hash_algorithm.take() { if let Some(hash_algorithm) = hash_algorithm.take() {
if Some(hash_algorithm) != algorithm { if Some(hash_algorithm) != algorithm {
return Err(type_error(format!( return Err(KeyObjectHandlePrehashedSignAndVerifyError::PrivateKeyDisallowsUsage {
"private key does not allow {} to be used, expected {}", actual: digest_type.to_string(),
digest_type, hash_algorithm.as_str() expected: hash_algorithm.as_str().to_string(),
))); });
} }
} }
if let Some(salt_length) = salt_length { if let Some(salt_length) = salt_length {
@ -242,17 +265,14 @@ impl KeyObjectHandle {
} }
}, },
_ => { _ => {
return Err(type_error(format!( return Err(KeyObjectHandlePrehashedSignAndVerifyError::DigestNotAllowedForRsaPssSignature(digest_type.to_string()));
"digest not allowed for RSA-PSS signature: {}",
digest_type
)))
} }
); );
Ok(pss.verify(&key.key, digest, signature).is_ok()) Ok(pss.verify(&key.key, digest, signature).is_ok())
} }
AsymmetricPublicKey::Dsa(key) => { AsymmetricPublicKey::Dsa(key) => {
let signature = dsa::Signature::from_der(signature) let signature = dsa::Signature::from_der(signature)
.map_err(|_| type_error("Invalid DSA signature"))?; .map_err(|_| KeyObjectHandlePrehashedSignAndVerifyError::InvalidDsaSignature)?;
Ok(key.verify_prehash(digest, &signature).is_ok()) Ok(key.verify_prehash(digest, &signature).is_ok())
} }
AsymmetricPublicKey::Ec(key) => match key { AsymmetricPublicKey::Ec(key) => match key {
@ -294,13 +314,11 @@ impl KeyObjectHandle {
} }
}, },
AsymmetricPublicKey::X25519(_) => { AsymmetricPublicKey::X25519(_) => {
Err(type_error("x25519 key cannot be used for verification")) Err(KeyObjectHandlePrehashedSignAndVerifyError::X25519KeyCannotBeUsedForVerification)
} }
AsymmetricPublicKey::Ed25519(_) => Err(type_error( AsymmetricPublicKey::Ed25519(_) => Err(KeyObjectHandlePrehashedSignAndVerifyError::Ed25519KeyCannotBeUsedForPrehashedVerification),
"Ed25519 key cannot be used for prehashed verification",
)),
AsymmetricPublicKey::Dh(_) => { AsymmetricPublicKey::Dh(_) => {
Err(type_error("DH key cannot be used for verification")) Err(KeyObjectHandlePrehashedSignAndVerifyError::DhKeyCannotBeUsedForVerification)
} }
} }
} }

View file

@ -1,11 +1,11 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
use deno_core::error::AnyError;
use deno_core::op2; use deno_core::op2;
use x509_parser::der_parser::asn1_rs::Any; use x509_parser::der_parser::asn1_rs::Any;
use x509_parser::der_parser::asn1_rs::Tag; use x509_parser::der_parser::asn1_rs::Tag;
use x509_parser::der_parser::oid::Oid; use x509_parser::der_parser::oid::Oid;
pub use x509_parser::error::X509Error;
use x509_parser::extensions; use x509_parser::extensions;
use x509_parser::pem; use x509_parser::pem;
use x509_parser::prelude::*; use x509_parser::prelude::*;
@ -65,7 +65,7 @@ impl<'a> Deref for CertificateView<'a> {
#[cppgc] #[cppgc]
pub fn op_node_x509_parse( pub fn op_node_x509_parse(
#[buffer] buf: &[u8], #[buffer] buf: &[u8],
) -> Result<Certificate, AnyError> { ) -> Result<Certificate, X509Error> {
let source = match pem::parse_x509_pem(buf) { let source = match pem::parse_x509_pem(buf) {
Ok((_, pem)) => CertificateSources::Pem(pem), Ok((_, pem)) => CertificateSources::Pem(pem),
Err(_) => CertificateSources::Der(buf.to_vec().into_boxed_slice()), Err(_) => CertificateSources::Der(buf.to_vec().into_boxed_slice()),
@ -81,7 +81,7 @@ pub fn op_node_x509_parse(
X509Certificate::from_der(buf).map(|(_, cert)| cert)? X509Certificate::from_der(buf).map(|(_, cert)| cert)?
} }
}; };
Ok::<_, AnyError>(CertificateView { cert }) Ok::<_, X509Error>(CertificateView { cert })
}, },
)?; )?;
@ -89,23 +89,23 @@ pub fn op_node_x509_parse(
} }
#[op2(fast)] #[op2(fast)]
pub fn op_node_x509_ca(#[cppgc] cert: &Certificate) -> Result<bool, AnyError> { pub fn op_node_x509_ca(#[cppgc] cert: &Certificate) -> bool {
let cert = cert.inner.get().deref(); let cert = cert.inner.get().deref();
Ok(cert.is_ca()) cert.is_ca()
} }
#[op2(fast)] #[op2(fast)]
pub fn op_node_x509_check_email( pub fn op_node_x509_check_email(
#[cppgc] cert: &Certificate, #[cppgc] cert: &Certificate,
#[string] email: &str, #[string] email: &str,
) -> Result<bool, AnyError> { ) -> bool {
let cert = cert.inner.get().deref(); let cert = cert.inner.get().deref();
let subject = cert.subject(); let subject = cert.subject();
if subject if subject
.iter_email() .iter_email()
.any(|e| e.as_str().unwrap_or("") == email) .any(|e| e.as_str().unwrap_or("") == email)
{ {
return Ok(true); return true;
} }
let subject_alt = cert let subject_alt = cert
@ -121,62 +121,60 @@ pub fn op_node_x509_check_email(
for name in &subject_alt.general_names { for name in &subject_alt.general_names {
if let extensions::GeneralName::RFC822Name(n) = name { if let extensions::GeneralName::RFC822Name(n) = name {
if *n == email { if *n == email {
return Ok(true); return true;
} }
} }
} }
} }
Ok(false) false
} }
#[op2] #[op2]
#[string] #[string]
pub fn op_node_x509_fingerprint( pub fn op_node_x509_fingerprint(#[cppgc] cert: &Certificate) -> Option<String> {
#[cppgc] cert: &Certificate, cert.fingerprint::<sha1::Sha1>()
) -> Result<Option<String>, AnyError> {
Ok(cert.fingerprint::<sha1::Sha1>())
} }
#[op2] #[op2]
#[string] #[string]
pub fn op_node_x509_fingerprint256( pub fn op_node_x509_fingerprint256(
#[cppgc] cert: &Certificate, #[cppgc] cert: &Certificate,
) -> Result<Option<String>, AnyError> { ) -> Option<String> {
Ok(cert.fingerprint::<sha2::Sha256>()) cert.fingerprint::<sha2::Sha256>()
} }
#[op2] #[op2]
#[string] #[string]
pub fn op_node_x509_fingerprint512( pub fn op_node_x509_fingerprint512(
#[cppgc] cert: &Certificate, #[cppgc] cert: &Certificate,
) -> Result<Option<String>, AnyError> { ) -> Option<String> {
Ok(cert.fingerprint::<sha2::Sha512>()) cert.fingerprint::<sha2::Sha512>()
} }
#[op2] #[op2]
#[string] #[string]
pub fn op_node_x509_get_issuer( pub fn op_node_x509_get_issuer(
#[cppgc] cert: &Certificate, #[cppgc] cert: &Certificate,
) -> Result<String, AnyError> { ) -> Result<String, X509Error> {
let cert = cert.inner.get().deref(); let cert = cert.inner.get().deref();
Ok(x509name_to_string(cert.issuer(), oid_registry())?) x509name_to_string(cert.issuer(), oid_registry())
} }
#[op2] #[op2]
#[string] #[string]
pub fn op_node_x509_get_subject( pub fn op_node_x509_get_subject(
#[cppgc] cert: &Certificate, #[cppgc] cert: &Certificate,
) -> Result<String, AnyError> { ) -> Result<String, X509Error> {
let cert = cert.inner.get().deref(); let cert = cert.inner.get().deref();
Ok(x509name_to_string(cert.subject(), oid_registry())?) x509name_to_string(cert.subject(), oid_registry())
} }
#[op2] #[op2]
#[cppgc] #[cppgc]
pub fn op_node_x509_public_key( pub fn op_node_x509_public_key(
#[cppgc] cert: &Certificate, #[cppgc] cert: &Certificate,
) -> Result<KeyObjectHandle, AnyError> { ) -> Result<KeyObjectHandle, super::keys::X509PublicKeyError> {
let cert = cert.inner.get().deref(); let cert = cert.inner.get().deref();
let public_key = &cert.tbs_certificate.subject_pki; let public_key = &cert.tbs_certificate.subject_pki;
@ -245,37 +243,29 @@ fn x509name_to_string(
#[op2] #[op2]
#[string] #[string]
pub fn op_node_x509_get_valid_from( pub fn op_node_x509_get_valid_from(#[cppgc] cert: &Certificate) -> String {
#[cppgc] cert: &Certificate,
) -> Result<String, AnyError> {
let cert = cert.inner.get().deref(); let cert = cert.inner.get().deref();
Ok(cert.validity().not_before.to_string()) cert.validity().not_before.to_string()
} }
#[op2] #[op2]
#[string] #[string]
pub fn op_node_x509_get_valid_to( pub fn op_node_x509_get_valid_to(#[cppgc] cert: &Certificate) -> String {
#[cppgc] cert: &Certificate,
) -> Result<String, AnyError> {
let cert = cert.inner.get().deref(); let cert = cert.inner.get().deref();
Ok(cert.validity().not_after.to_string()) cert.validity().not_after.to_string()
} }
#[op2] #[op2]
#[string] #[string]
pub fn op_node_x509_get_serial_number( pub fn op_node_x509_get_serial_number(#[cppgc] cert: &Certificate) -> String {
#[cppgc] cert: &Certificate,
) -> Result<String, AnyError> {
let cert = cert.inner.get().deref(); let cert = cert.inner.get().deref();
let mut s = cert.serial.to_str_radix(16); let mut s = cert.serial.to_str_radix(16);
s.make_ascii_uppercase(); s.make_ascii_uppercase();
Ok(s) s
} }
#[op2(fast)] #[op2(fast)]
pub fn op_node_x509_key_usage( pub fn op_node_x509_key_usage(#[cppgc] cert: &Certificate) -> u16 {
#[cppgc] cert: &Certificate,
) -> Result<u16, AnyError> {
let cert = cert.inner.get().deref(); let cert = cert.inner.get().deref();
let key_usage = cert let key_usage = cert
.extensions() .extensions()
@ -286,5 +276,5 @@ pub fn op_node_x509_key_usage(
_ => None, _ => None,
}); });
Ok(key_usage.map(|k| k.flags).unwrap_or(0)) key_usage.map(|k| k.flags).unwrap_or(0)
} }

View file

@ -1051,6 +1051,34 @@ mod node {
use super::get_serde_json_error_class; use super::get_serde_json_error_class;
use super::get_url_parse_error_class; use super::get_url_parse_error_class;
pub use deno_node::ops::blocklist::BlocklistError; pub use deno_node::ops::blocklist::BlocklistError;
pub use deno_node::ops::crypto::cipher::CipherContextError;
pub use deno_node::ops::crypto::cipher::CipherError;
pub use deno_node::ops::crypto::cipher::DecipherContextError;
pub use deno_node::ops::crypto::cipher::DecipherError;
pub use deno_node::ops::crypto::digest::HashError;
pub use deno_node::ops::crypto::keys::AsymmetricPrivateKeyDerError;
pub use deno_node::ops::crypto::keys::AsymmetricPrivateKeyError;
pub use deno_node::ops::crypto::keys::AsymmetricPublicKeyDerError;
pub use deno_node::ops::crypto::keys::AsymmetricPublicKeyError;
pub use deno_node::ops::crypto::keys::AsymmetricPublicKeyJwkError;
pub use deno_node::ops::crypto::keys::EcJwkError;
pub use deno_node::ops::crypto::keys::EdRawError;
pub use deno_node::ops::crypto::keys::ExportPrivateKeyPemError;
pub use deno_node::ops::crypto::keys::ExportPublicKeyPemError;
pub use deno_node::ops::crypto::keys::GenerateRsaPssError;
pub use deno_node::ops::crypto::keys::RsaJwkError;
pub use deno_node::ops::crypto::keys::RsaPssParamsParseError;
pub use deno_node::ops::crypto::keys::X509PublicKeyError;
pub use deno_node::ops::crypto::sign::KeyObjectHandlePrehashedSignAndVerifyError;
pub use deno_node::ops::crypto::x509::X509Error;
pub use deno_node::ops::crypto::DiffieHellmanError;
pub use deno_node::ops::crypto::EcdhEncodePubKey;
pub use deno_node::ops::crypto::HkdfError;
pub use deno_node::ops::crypto::Pbkdf2Error;
pub use deno_node::ops::crypto::PrivateEncryptDecryptError;
pub use deno_node::ops::crypto::ScryptAsyncError;
pub use deno_node::ops::crypto::SignEd25519Error;
pub use deno_node::ops::crypto::VerifyEd25519Error;
pub use deno_node::ops::fs::FsError; pub use deno_node::ops::fs::FsError;
pub use deno_node::ops::http2::Http2Error; pub use deno_node::ops::http2::Http2Error;
pub use deno_node::ops::idna::IdnaError; pub use deno_node::ops::idna::IdnaError;
@ -1189,6 +1217,324 @@ mod node {
ZlibError::Other(e) => get_error_class_name(e).unwrap_or("Error"), ZlibError::Other(e) => get_error_class_name(e).unwrap_or("Error"),
} }
} }
pub fn get_crypto_cipher_context_error(
e: &CipherContextError,
) -> &'static str {
match e {
CipherContextError::ContextInUse => "TypeError",
CipherContextError::Cipher(e) => get_crypto_cipher_error(e),
CipherContextError::Resource(e) => {
get_error_class_name(e).unwrap_or("Error")
}
}
}
pub fn get_crypto_cipher_error(e: &CipherError) -> &'static str {
match e {
CipherError::InvalidIvLength => "TypeError",
CipherError::InvalidKeyLength => "RangeError",
CipherError::InvalidInitializationVector => "TypeError",
CipherError::CannotPadInputData => "TypeError",
CipherError::UnknownCipher(_) => "TypeError",
}
}
pub fn get_crypto_decipher_context_error(
e: &DecipherContextError,
) -> &'static str {
match e {
DecipherContextError::ContextInUse => "TypeError",
DecipherContextError::Decipher(e) => get_crypto_decipher_error(e),
DecipherContextError::Resource(e) => {
get_error_class_name(e).unwrap_or("Error")
}
}
}
pub fn get_crypto_decipher_error(e: &DecipherError) -> &'static str {
match e {
DecipherError::InvalidIvLength => "TypeError",
DecipherError::InvalidKeyLength => "RangeError",
DecipherError::InvalidInitializationVector => "TypeError",
DecipherError::CannotUnpadInputData => "TypeError",
DecipherError::DataAuthenticationFailed => "TypeError",
DecipherError::SetAutoPaddingFalseAes128GcmUnsupported => "TypeError",
DecipherError::SetAutoPaddingFalseAes256GcmUnsupported => "TypeError",
DecipherError::UnknownCipher(_) => "TypeError",
}
}
pub fn get_x509_error(_: &X509Error) -> &'static str {
"Error"
}
pub fn get_crypto_key_object_handle_prehashed_sign_and_verify_error(
e: &KeyObjectHandlePrehashedSignAndVerifyError,
) -> &'static str {
match e {
KeyObjectHandlePrehashedSignAndVerifyError::InvalidDsaSignatureEncoding => "TypeError",
KeyObjectHandlePrehashedSignAndVerifyError::KeyIsNotPrivate => "TypeError",
KeyObjectHandlePrehashedSignAndVerifyError::DigestNotAllowedForRsaSignature(_) => "TypeError",
KeyObjectHandlePrehashedSignAndVerifyError::FailedToSignDigestWithRsa => "Error",
KeyObjectHandlePrehashedSignAndVerifyError::DigestNotAllowedForRsaPssSignature(_) => "TypeError",
KeyObjectHandlePrehashedSignAndVerifyError::FailedToSignDigestWithRsaPss => "Error",
KeyObjectHandlePrehashedSignAndVerifyError::FailedToSignDigestWithDsa => "TypeError",
KeyObjectHandlePrehashedSignAndVerifyError::RsaPssHashAlgorithmUnsupported => "TypeError",
KeyObjectHandlePrehashedSignAndVerifyError::PrivateKeyDisallowsUsage { .. } => "TypeError",
KeyObjectHandlePrehashedSignAndVerifyError::FailedToSignDigest => "TypeError",
KeyObjectHandlePrehashedSignAndVerifyError::X25519KeyCannotBeUsedForSigning => "TypeError",
KeyObjectHandlePrehashedSignAndVerifyError::Ed25519KeyCannotBeUsedForPrehashedSigning => "TypeError",
KeyObjectHandlePrehashedSignAndVerifyError::DhKeyCannotBeUsedForSigning => "TypeError",
KeyObjectHandlePrehashedSignAndVerifyError::KeyIsNotPublicOrPrivate => "TypeError",
KeyObjectHandlePrehashedSignAndVerifyError::InvalidDsaSignature => "TypeError",
KeyObjectHandlePrehashedSignAndVerifyError::X25519KeyCannotBeUsedForVerification => "TypeError",
KeyObjectHandlePrehashedSignAndVerifyError::Ed25519KeyCannotBeUsedForPrehashedVerification => "TypeError",
KeyObjectHandlePrehashedSignAndVerifyError::DhKeyCannotBeUsedForVerification => "TypeError",
}
}
pub fn get_crypto_hash_error(_: &HashError) -> &'static str {
"Error"
}
pub fn get_asymmetric_public_key_jwk_error(
e: &AsymmetricPublicKeyJwkError,
) -> &'static str {
match e {
AsymmetricPublicKeyJwkError::UnsupportedJwkEcCurveP224 => "TypeError",
AsymmetricPublicKeyJwkError::JwkExportNotImplementedForKeyType => {
"TypeError"
}
AsymmetricPublicKeyJwkError::KeyIsNotAsymmetricPublicKey => "TypeError",
}
}
pub fn get_generate_rsa_pss_error(_: &GenerateRsaPssError) -> &'static str {
"TypeError"
}
pub fn get_asymmetric_private_key_der_error(
e: &AsymmetricPrivateKeyDerError,
) -> &'static str {
match e {
AsymmetricPrivateKeyDerError::KeyIsNotAsymmetricPrivateKey => "TypeError",
AsymmetricPrivateKeyDerError::InvalidRsaPrivateKey => "TypeError",
AsymmetricPrivateKeyDerError::ExportingNonRsaPrivateKeyAsPkcs1Unsupported => "TypeError",
AsymmetricPrivateKeyDerError::InvalidEcPrivateKey => "TypeError",
AsymmetricPrivateKeyDerError::ExportingNonEcPrivateKeyAsSec1Unsupported => "TypeError",
AsymmetricPrivateKeyDerError::ExportingNonRsaPssPrivateKeyAsPkcs8Unsupported => "Error",
AsymmetricPrivateKeyDerError::InvalidDsaPrivateKey => "TypeError",
AsymmetricPrivateKeyDerError::InvalidX25519PrivateKey => "TypeError",
AsymmetricPrivateKeyDerError::InvalidEd25519PrivateKey => "TypeError",
AsymmetricPrivateKeyDerError::InvalidDhPrivateKey => "TypeError",
AsymmetricPrivateKeyDerError::UnsupportedKeyType(_) => "TypeError",
}
}
pub fn get_asymmetric_public_key_der_error(
_: &AsymmetricPublicKeyDerError,
) -> &'static str {
"TypeError"
}
pub fn get_export_public_key_pem_error(
e: &ExportPublicKeyPemError,
) -> &'static str {
match e {
ExportPublicKeyPemError::AsymmetricPublicKeyDer(e) => {
get_asymmetric_public_key_der_error(e)
}
ExportPublicKeyPemError::VeryLargeData => "TypeError",
ExportPublicKeyPemError::Der(_) => "Error",
}
}
pub fn get_export_private_key_pem_error(
e: &ExportPrivateKeyPemError,
) -> &'static str {
match e {
ExportPrivateKeyPemError::AsymmetricPublicKeyDer(e) => {
get_asymmetric_private_key_der_error(e)
}
ExportPrivateKeyPemError::VeryLargeData => "TypeError",
ExportPrivateKeyPemError::Der(_) => "Error",
}
}
pub fn get_x509_public_key_error(e: &X509PublicKeyError) -> &'static str {
match e {
X509PublicKeyError::X509(_) => "Error",
X509PublicKeyError::Rsa(_) => "Error",
X509PublicKeyError::Asn1(_) => "Error",
X509PublicKeyError::Ec(_) => "Error",
X509PublicKeyError::UnsupportedEcNamedCurve => "TypeError",
X509PublicKeyError::MissingEcParameters => "TypeError",
X509PublicKeyError::MalformedDssPublicKey => "TypeError",
X509PublicKeyError::UnsupportedX509KeyType => "TypeError",
}
}
pub fn get_rsa_jwk_error(e: &RsaJwkError) -> &'static str {
match e {
RsaJwkError::Base64(_) => "Error",
RsaJwkError::Rsa(_) => "Error",
RsaJwkError::MissingRsaPrivateComponent => "TypeError",
}
}
pub fn get_ec_jwk_error(e: &EcJwkError) -> &'static str {
match e {
EcJwkError::Ec(_) => "Error",
EcJwkError::UnsupportedCurve(_) => "TypeError",
}
}
pub fn get_ed_raw_error(e: &EdRawError) -> &'static str {
match e {
EdRawError::Ed25519Signature(_) => "Error",
EdRawError::InvalidEd25519Key => "TypeError",
EdRawError::UnsupportedCurve => "TypeError",
}
}
pub fn get_pbkdf2_error(e: &Pbkdf2Error) -> &'static str {
match e {
Pbkdf2Error::UnsupportedDigest(_) => "TypeError",
Pbkdf2Error::Join(_) => "Error",
}
}
pub fn get_scrypt_async_error(e: &ScryptAsyncError) -> &'static str {
match e {
ScryptAsyncError::Join(_) => "Error",
ScryptAsyncError::Other(e) => get_error_class_name(e).unwrap_or("Error"),
}
}
pub fn get_hkdf_error_error(e: &HkdfError) -> &'static str {
match e {
HkdfError::ExpectedSecretKey => "TypeError",
HkdfError::HkdfExpandFailed => "TypeError",
HkdfError::UnsupportedDigest(_) => "TypeError",
HkdfError::Join(_) => "Error",
}
}
pub fn get_rsa_pss_params_parse_error(
_: &RsaPssParamsParseError,
) -> &'static str {
"TypeError"
}
pub fn get_asymmetric_private_key_error(
e: &AsymmetricPrivateKeyError,
) -> &'static str {
match e {
AsymmetricPrivateKeyError::InvalidPemPrivateKeyInvalidUtf8(_) => "TypeError",
AsymmetricPrivateKeyError::InvalidEncryptedPemPrivateKey => "TypeError",
AsymmetricPrivateKeyError::InvalidPemPrivateKey => "TypeError",
AsymmetricPrivateKeyError::EncryptedPrivateKeyRequiresPassphraseToDecrypt => "TypeError",
AsymmetricPrivateKeyError::InvalidPkcs1PrivateKey => "TypeError",
AsymmetricPrivateKeyError::InvalidSec1PrivateKey => "TypeError",
AsymmetricPrivateKeyError::UnsupportedPemLabel(_) => "TypeError",
AsymmetricPrivateKeyError::RsaPssParamsParse(e) => get_rsa_pss_params_parse_error(e),
AsymmetricPrivateKeyError::InvalidEncryptedPkcs8PrivateKey => "TypeError",
AsymmetricPrivateKeyError::InvalidPkcs8PrivateKey => "TypeError",
AsymmetricPrivateKeyError::Pkcs1PrivateKeyDoesNotSupportEncryptionWithPassphrase => "TypeError",
AsymmetricPrivateKeyError::Sec1PrivateKeyDoesNotSupportEncryptionWithPassphrase => "TypeError",
AsymmetricPrivateKeyError::UnsupportedEcNamedCurve => "TypeError",
AsymmetricPrivateKeyError::InvalidPrivateKey => "TypeError",
AsymmetricPrivateKeyError::InvalidDsaPrivateKey => "TypeError",
AsymmetricPrivateKeyError::MalformedOrMissingNamedCurveInEcParameters => "TypeError",
AsymmetricPrivateKeyError::UnsupportedKeyType(_) => "TypeError",
AsymmetricPrivateKeyError::UnsupportedKeyFormat(_) => "TypeError",
AsymmetricPrivateKeyError::InvalidX25519PrivateKey => "TypeError",
AsymmetricPrivateKeyError::X25519PrivateKeyIsWrongLength => "TypeError",
AsymmetricPrivateKeyError::InvalidEd25519PrivateKey => "TypeError",
AsymmetricPrivateKeyError::MissingDhParameters => "TypeError",
AsymmetricPrivateKeyError::UnsupportedPrivateKeyOid => "TypeError",
}
}
pub fn get_asymmetric_public_key_error(
e: &AsymmetricPublicKeyError,
) -> &'static str {
match e {
AsymmetricPublicKeyError::InvalidPemPrivateKeyInvalidUtf8(_) => {
"TypeError"
}
AsymmetricPublicKeyError::InvalidPemPublicKey => "TypeError",
AsymmetricPublicKeyError::InvalidPkcs1PublicKey => "TypeError",
AsymmetricPublicKeyError::AsymmetricPrivateKey(e) => {
get_asymmetric_private_key_error(e)
}
AsymmetricPublicKeyError::InvalidX509Certificate => "TypeError",
AsymmetricPublicKeyError::X509(_) => "Error",
AsymmetricPublicKeyError::X509PublicKey(e) => {
get_x509_public_key_error(e)
}
AsymmetricPublicKeyError::UnsupportedPemLabel(_) => "TypeError",
AsymmetricPublicKeyError::InvalidSpkiPublicKey => "TypeError",
AsymmetricPublicKeyError::UnsupportedKeyType(_) => "TypeError",
AsymmetricPublicKeyError::UnsupportedKeyFormat(_) => "TypeError",
AsymmetricPublicKeyError::Spki(_) => "Error",
AsymmetricPublicKeyError::Pkcs1(_) => "Error",
AsymmetricPublicKeyError::RsaPssParamsParse(_) => "TypeError",
AsymmetricPublicKeyError::MalformedDssPublicKey => "TypeError",
AsymmetricPublicKeyError::MalformedOrMissingNamedCurveInEcParameters => {
"TypeError"
}
AsymmetricPublicKeyError::MalformedOrMissingPublicKeyInEcSpki => {
"TypeError"
}
AsymmetricPublicKeyError::Ec(_) => "Error",
AsymmetricPublicKeyError::UnsupportedEcNamedCurve => "TypeError",
AsymmetricPublicKeyError::MalformedOrMissingPublicKeyInX25519Spki => {
"TypeError"
}
AsymmetricPublicKeyError::X25519PublicKeyIsTooShort => "TypeError",
AsymmetricPublicKeyError::InvalidEd25519PublicKey => "TypeError",
AsymmetricPublicKeyError::MissingDhParameters => "TypeError",
AsymmetricPublicKeyError::MalformedDhParameters => "TypeError",
AsymmetricPublicKeyError::MalformedOrMissingPublicKeyInDhSpki => {
"TypeError"
}
AsymmetricPublicKeyError::UnsupportedPrivateKeyOid => "TypeError",
}
}
pub fn get_private_encrypt_decrypt_error(
e: &PrivateEncryptDecryptError,
) -> &'static str {
match e {
PrivateEncryptDecryptError::Pkcs8(_) => "Error",
PrivateEncryptDecryptError::Spki(_) => "Error",
PrivateEncryptDecryptError::Utf8(_) => "Error",
PrivateEncryptDecryptError::Rsa(_) => "Error",
PrivateEncryptDecryptError::UnknownPadding => "TypeError",
}
}
pub fn get_ecdh_encode_pub_key_error(e: &EcdhEncodePubKey) -> &'static str {
match e {
EcdhEncodePubKey::InvalidPublicKey => "TypeError",
EcdhEncodePubKey::UnsupportedCurve => "TypeError",
EcdhEncodePubKey::Sec1(_) => "Error",
}
}
pub fn get_diffie_hellman_error(_: &DiffieHellmanError) -> &'static str {
"TypeError"
}
pub fn get_sign_ed25519_error(_: &SignEd25519Error) -> &'static str {
"TypeError"
}
pub fn get_verify_ed25519_error(_: &VerifyEd25519Error) -> &'static str {
"TypeError"
}
} }
fn get_os_error(error: &OsError) -> &'static str { fn get_os_error(error: &OsError) -> &'static str {
@ -1273,6 +1619,114 @@ pub fn get_error_class_name(e: &AnyError) -> Option<&'static str> {
e.downcast_ref::<node::ZlibError>() e.downcast_ref::<node::ZlibError>()
.map(node::get_zlib_error) .map(node::get_zlib_error)
}) })
.or_else(|| {
e.downcast_ref::<node::CipherError>()
.map(node::get_crypto_cipher_error)
})
.or_else(|| {
e.downcast_ref::<node::CipherContextError>()
.map(node::get_crypto_cipher_context_error)
})
.or_else(|| {
e.downcast_ref::<node::DecipherError>()
.map(node::get_crypto_decipher_error)
})
.or_else(|| {
e.downcast_ref::<node::DecipherContextError>()
.map(node::get_crypto_decipher_context_error)
})
.or_else(|| {
e.downcast_ref::<node::X509Error>()
.map(node::get_x509_error)
})
.or_else(|| {
e.downcast_ref::<node::KeyObjectHandlePrehashedSignAndVerifyError>()
.map(node::get_crypto_key_object_handle_prehashed_sign_and_verify_error)
})
.or_else(|| {
e.downcast_ref::<node::HashError>()
.map(node::get_crypto_hash_error)
})
.or_else(|| {
e.downcast_ref::<node::AsymmetricPublicKeyJwkError>()
.map(node::get_asymmetric_public_key_jwk_error)
})
.or_else(|| {
e.downcast_ref::<node::GenerateRsaPssError>()
.map(node::get_generate_rsa_pss_error)
})
.or_else(|| {
e.downcast_ref::<node::AsymmetricPrivateKeyDerError>()
.map(node::get_asymmetric_private_key_der_error)
})
.or_else(|| {
e.downcast_ref::<node::AsymmetricPublicKeyDerError>()
.map(node::get_asymmetric_public_key_der_error)
})
.or_else(|| {
e.downcast_ref::<node::ExportPublicKeyPemError>()
.map(node::get_export_public_key_pem_error)
})
.or_else(|| {
e.downcast_ref::<node::ExportPrivateKeyPemError>()
.map(node::get_export_private_key_pem_error)
})
.or_else(|| {
e.downcast_ref::<node::RsaJwkError>()
.map(node::get_rsa_jwk_error)
})
.or_else(|| {
e.downcast_ref::<node::EcJwkError>()
.map(node::get_ec_jwk_error)
})
.or_else(|| {
e.downcast_ref::<node::EdRawError>()
.map(node::get_ed_raw_error)
})
.or_else(|| {
e.downcast_ref::<node::Pbkdf2Error>()
.map(node::get_pbkdf2_error)
})
.or_else(|| {
e.downcast_ref::<node::ScryptAsyncError>()
.map(node::get_scrypt_async_error)
})
.or_else(|| {
e.downcast_ref::<node::HkdfError>()
.map(node::get_hkdf_error_error)
})
.or_else(|| {
e.downcast_ref::<node::RsaPssParamsParseError>()
.map(node::get_rsa_pss_params_parse_error)
})
.or_else(|| {
e.downcast_ref::<node::AsymmetricPrivateKeyError>()
.map(node::get_asymmetric_private_key_error)
})
.or_else(|| {
e.downcast_ref::<node::AsymmetricPublicKeyError>()
.map(node::get_asymmetric_public_key_error)
})
.or_else(|| {
e.downcast_ref::<node::PrivateEncryptDecryptError>()
.map(node::get_private_encrypt_decrypt_error)
})
.or_else(|| {
e.downcast_ref::<node::EcdhEncodePubKey>()
.map(node::get_ecdh_encode_pub_key_error)
})
.or_else(|| {
e.downcast_ref::<node::DiffieHellmanError>()
.map(node::get_diffie_hellman_error)
})
.or_else(|| {
e.downcast_ref::<node::SignEd25519Error>()
.map(node::get_sign_ed25519_error)
})
.or_else(|| {
e.downcast_ref::<node::VerifyEd25519Error>()
.map(node::get_verify_ed25519_error)
})
.or_else(|| e.downcast_ref::<NApiError>().map(get_napi_error_class)) .or_else(|| e.downcast_ref::<NApiError>().map(get_napi_error_class))
.or_else(|| e.downcast_ref::<WebError>().map(get_web_error_class)) .or_else(|| e.downcast_ref::<WebError>().map(get_web_error_class))
.or_else(|| { .or_else(|| {