keymgr: Use Box<dyn EncodableKey> instead of Box<dyn Any>.

Prompted by https://gitlab.torproject.org/tpo/core/arti/-/merge_requests/1337#note_2917701

This will make it harder to accidentally return the wrong value from
`Keystore::get` (the returned value is now at least guaranteed to
implement `EncodableKey`).

Closes #937
This commit is contained in:
Gabriela Moldovan 2023-07-10 14:20:17 +01:00
parent 9f3619d5c9
commit 9cde64c2c8
5 changed files with 21 additions and 10 deletions

1
Cargo.lock generated
View File

@ -4550,6 +4550,7 @@ name = "tor-keymgr"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"derive_more", "derive_more",
"downcast-rs",
"dyn-clone", "dyn-clone",
"fs-mistrust", "fs-mistrust",
"itertools 0.10.5", "itertools 0.10.5",

View File

@ -25,6 +25,7 @@ experimental = ["keymgr"]
[dependencies] [dependencies]
derive_more = "0.99.3" derive_more = "0.99.3"
downcast-rs = "1.2.0"
dyn-clone = "1.0.11" dyn-clone = "1.0.11"
fs-mistrust = { path = "../fs-mistrust", version = "0.7.1", features = ["serde", "walkdir"] } fs-mistrust = { path = "../fs-mistrust", version = "0.7.1", features = ["serde", "walkdir"] }
itertools = "0.10.1" itertools = "0.10.1"

View File

@ -216,7 +216,10 @@ mod tests {
fn wrong_key_type() { fn wrong_key_type() {
let key_type = KeyType::Ed25519Keypair; let key_type = KeyType::Ed25519Keypair;
let key = UnparsedOpenSshKey::new(OPENSSH_DSA.into(), PathBuf::from("/test/path")); let key = UnparsedOpenSshKey::new(OPENSSH_DSA.into(), PathBuf::from("/test/path"));
let err = key_type.parse_ssh_format_erased(key).unwrap_err(); let err = key_type
.parse_ssh_format_erased(key)
.map(|_| "<type erased key>")
.unwrap_err();
assert_eq!( assert_eq!(
err.to_string(), err.to_string(),
@ -232,7 +235,10 @@ mod tests {
fn invalid_ed25519_key() { fn invalid_ed25519_key() {
let key_type = KeyType::Ed25519Keypair; let key_type = KeyType::Ed25519Keypair;
let key = UnparsedOpenSshKey::new(OPENSSH_ED25519_BAD.into(), PathBuf::from("/test/path")); let key = UnparsedOpenSshKey::new(OPENSSH_ED25519_BAD.into(), PathBuf::from("/test/path"));
let err = key_type.parse_ssh_format_erased(key).unwrap_err(); let err = key_type
.parse_ssh_format_erased(key)
.map(|_| "<type erased key>")
.unwrap_err();
assert_eq!( assert_eq!(
err.to_string(), err.to_string(),

View File

@ -8,10 +8,10 @@ use tor_llcrypto::pk::{curve25519, ed25519};
use crate::key_type::KeyType; use crate::key_type::KeyType;
use crate::{KeySpecifier, Result}; use crate::{KeySpecifier, Result};
use std::any::Any; use downcast_rs::{impl_downcast, Downcast};
/// A type-erased key returned by a [`Keystore`]. /// A type-erased key returned by a [`Keystore`].
pub type ErasedKey = Box<dyn Any>; pub type ErasedKey = Box<dyn EncodableKey>;
/// A generic key store. /// A generic key store.
// //
@ -63,13 +63,15 @@ pub trait Keystore: Send + Sync + 'static {
/// A key that can be serialized to, and deserialized from, a format used by a /// A key that can be serialized to, and deserialized from, a format used by a
/// [`Keystore`](crate::Keystore). /// [`Keystore`](crate::Keystore).
pub trait EncodableKey { pub trait EncodableKey: Downcast {
/// The type of the key. /// The type of the key.
fn key_type() -> KeyType fn key_type() -> KeyType
where where
Self: Sized; Self: Sized;
} }
impl_downcast!(EncodableKey);
impl EncodableKey for curve25519::StaticSecret { impl EncodableKey for curve25519::StaticSecret {
fn key_type() -> KeyType fn key_type() -> KeyType
where where

View File

@ -299,12 +299,13 @@ mod tests {
let erased_kp = KeyType::Ed25519Keypair let erased_kp = KeyType::Ed25519Keypair
.parse_ssh_format_erased(key) .parse_ssh_format_erased(key)
.unwrap(); .unwrap();
let Ok(key) = erased_kp.downcast::<ed25519::Keypair>() else {
panic!("failed to downcast key to ed25519::Keypair")
};
key_store key_store
.insert( .insert(&*key, &TestSpecifier, KeyType::Ed25519Keypair)
&*erased_kp.downcast::<ed25519::Keypair>().unwrap(),
&TestSpecifier,
KeyType::Ed25519Keypair,
)
.unwrap(); .unwrap();
// Found! // Found!