Skip to main content

tuwunel_service/server_keys/
mod.rs

1mod acquire;
2mod get;
3mod keypair;
4mod request;
5mod sign;
6mod verify;
7
8use std::{collections::BTreeMap, sync::Arc, time::Duration};
9
10use futures::StreamExt;
11use ruma::{
12	CanonicalJsonObject, MilliSecondsSinceUnixEpoch, OwnedServerSigningKeyId, ServerName,
13	ServerSigningKeyId,
14	api::federation::discovery::{ServerSigningKeys, VerifyKey},
15	room_version_rules::RoomVersionRules,
16	serde::Raw,
17	signatures::{Ed25519KeyPair, PublicKeyMap, PublicKeySet},
18};
19use serde_json::value::RawValue as RawJsonValue;
20use tuwunel_core::{
21	Result, implement,
22	utils::{IterStream, timepoint_from_now},
23};
24use tuwunel_database::{Deserialized, Json, Map};
25
26pub struct Service {
27	keypair: Box<Ed25519KeyPair>,
28	verify_keys: VerifyKeys,
29	minimum_valid: Duration,
30	services: Arc<crate::services::OnceServices>,
31	db: Data,
32}
33
34struct Data {
35	server_signingkeys: Arc<Map>,
36}
37
38pub type VerifyKeys = BTreeMap<OwnedServerSigningKeyId, VerifyKey>;
39pub type PubKeyMap = PublicKeyMap;
40pub type PubKeys = PublicKeySet;
41
42impl crate::Service for Service {
43	fn build(args: &crate::Args<'_>) -> Result<Arc<Self>> {
44		let minimum_valid = Duration::from_hours(1);
45
46		let (keypair, verify_keys) = keypair::init(args.db)?;
47		debug_assert!(verify_keys.len() == 1, "only one active verify_key supported");
48
49		Ok(Arc::new(Self {
50			keypair,
51			verify_keys,
52			minimum_valid,
53			services: args.services.clone(),
54			db: Data {
55				server_signingkeys: args.db["server_signingkeys"].clone(),
56			},
57		}))
58	}
59
60	fn name(&self) -> &str { crate::service::make_name(std::module_path!()) }
61}
62
63#[implement(Service)]
64#[inline]
65#[must_use]
66pub fn keypair(&self) -> &Ed25519KeyPair { &self.keypair }
67
68#[implement(Service)]
69#[inline]
70#[must_use]
71pub fn active_key_id(&self) -> &ServerSigningKeyId { self.active_verify_key().0 }
72
73#[implement(Service)]
74#[inline]
75#[must_use]
76pub fn active_verify_key(&self) -> (&ServerSigningKeyId, &VerifyKey) {
77	debug_assert!(self.verify_keys.len() <= 1, "more than one active verify_key");
78	self.verify_keys
79		.iter()
80		.next()
81		.map(|(id, key)| (id.as_ref(), key))
82		.expect("missing active verify_key")
83}
84
85#[implement(Service)]
86async fn add_signing_keys(&self, new_keys: ServerSigningKeys) {
87	let origin = &new_keys.server_name;
88
89	// (timo) Not atomic, but this is not critical
90	let mut keys: ServerSigningKeys = self
91		.db
92		.server_signingkeys
93		.get(origin)
94		.await
95		.deserialized()
96		.unwrap_or_else(|_| {
97			// Just insert "now", it doesn't matter
98			ServerSigningKeys::new(origin.to_owned(), MilliSecondsSinceUnixEpoch::now())
99		});
100
101	keys.verify_keys.extend(new_keys.verify_keys);
102	keys.old_verify_keys
103		.extend(new_keys.old_verify_keys);
104
105	self.db
106		.server_signingkeys
107		.raw_put(origin, Json(&keys));
108}
109
110#[implement(Service)]
111pub async fn required_keys_exist(
112	&self,
113	object: &CanonicalJsonObject,
114	rules: &RoomVersionRules,
115) -> bool {
116	use ruma::signatures::required_keys;
117
118	let Ok(required_keys) = required_keys(object, &rules.signatures) else {
119		return false;
120	};
121
122	required_keys
123		.iter()
124		.flat_map(|(server, key_ids)| key_ids.iter().map(move |key_id| (server, key_id)))
125		.stream()
126		.all(|(server, key_id)| self.verify_key_exists(server, key_id))
127		.await
128}
129
130#[implement(Service)]
131pub async fn verify_key_exists(&self, origin: &ServerName, key_id: &ServerSigningKeyId) -> bool {
132	type KeysMap<'a> = BTreeMap<&'a ServerSigningKeyId, &'a RawJsonValue>;
133
134	let Ok(keys) = self
135		.db
136		.server_signingkeys
137		.get(origin)
138		.await
139		.deserialized::<Raw<ServerSigningKeys>>()
140	else {
141		return false;
142	};
143
144	if let Ok(Some(verify_keys)) = keys.get_field::<KeysMap<'_>>("verify_keys")
145		&& verify_keys.contains_key(key_id)
146	{
147		return true;
148	}
149
150	if let Ok(Some(old_verify_keys)) = keys.get_field::<KeysMap<'_>>("old_verify_keys")
151		&& old_verify_keys.contains_key(key_id)
152	{
153		return true;
154	}
155
156	false
157}
158
159#[implement(Service)]
160pub async fn verify_keys_for(&self, origin: &ServerName) -> VerifyKeys {
161	let mut keys = self
162		.signing_keys_for(origin)
163		.await
164		.map(|keys| merge_old_keys(keys).verify_keys)
165		.unwrap_or(BTreeMap::new());
166
167	if self.services.globals.server_is_ours(origin) {
168		keys.extend(self.verify_keys.clone());
169	}
170
171	keys
172}
173
174#[implement(Service)]
175pub async fn signing_keys_for(&self, origin: &ServerName) -> Result<ServerSigningKeys> {
176	self.db
177		.server_signingkeys
178		.get(origin)
179		.await
180		.deserialized()
181}
182
183#[implement(Service)]
184fn minimum_valid_ts(&self) -> MilliSecondsSinceUnixEpoch {
185	let timepoint =
186		timepoint_from_now(self.minimum_valid).expect("SystemTime should not overflow");
187
188	MilliSecondsSinceUnixEpoch::from_system_time(timepoint).expect("UInt should not overflow")
189}
190
191fn merge_old_keys(mut keys: ServerSigningKeys) -> ServerSigningKeys {
192	keys.verify_keys.extend(
193		keys.old_verify_keys
194			.clone()
195			.into_iter()
196			.map(|(key_id, old)| (key_id, VerifyKey::new(old.key))),
197	);
198
199	keys
200}
201
202fn extract_key(mut keys: ServerSigningKeys, key_id: &ServerSigningKeyId) -> Option<VerifyKey> {
203	keys.verify_keys.remove(key_id).or_else(|| {
204		keys.old_verify_keys
205			.remove(key_id)
206			.map(|old| VerifyKey::new(old.key))
207	})
208}
209
210fn key_exists(keys: &ServerSigningKeys, key_id: &ServerSigningKeyId) -> bool {
211	keys.verify_keys.contains_key(key_id) || keys.old_verify_keys.contains_key(key_id)
212}