tuwunel_service/server_keys/
mod.rs1mod acquire;
8mod get;
9mod keypair;
10mod request;
11mod sign;
12mod verify;
13
14use std::{collections::BTreeMap, sync::Arc, time::Duration};
15
16use futures::StreamExt;
17use ruma::{
18 CanonicalJsonObject, MilliSecondsSinceUnixEpoch, OwnedServerSigningKeyId, ServerName,
19 ServerSigningKeyId,
20 api::federation::discovery::{ServerSigningKeys, VerifyKey},
21 room_version_rules::RoomVersionRules,
22 serde::Raw,
23 signatures::{Ed25519KeyPair, PublicKeyMap, PublicKeySet},
24};
25use serde_json::value::RawValue as RawJsonValue;
26use tuwunel_core::{
27 Result, implement,
28 utils::{IterStream, timepoint_from_now},
29};
30use tuwunel_database::{Deserialized, Json, Map};
31
32pub struct Service {
37 keypair: Box<Ed25519KeyPair>,
38 verify_keys: VerifyKeys,
39 minimum_valid: Duration,
40 services: Arc<crate::services::OnceServices>,
41 db: Data,
42}
43
44struct Data {
45 server_signingkeys: Arc<Map>,
46}
47
48pub type VerifyKeys = BTreeMap<OwnedServerSigningKeyId, VerifyKey>;
53
54pub type PubKeyMap = PublicKeyMap;
58
59pub type PubKeys = PublicKeySet;
63
64impl crate::Service for Service {
65 fn build(args: &crate::Args<'_>) -> Result<Arc<Self>> {
66 let minimum_valid = Duration::from_hours(1);
67
68 let (keypair, verify_keys) = keypair::init(args.db)?;
69 debug_assert!(verify_keys.len() == 1, "only one active verify_key supported");
70
71 Ok(Arc::new(Self {
72 keypair,
73 verify_keys,
74 minimum_valid,
75 services: args.services.clone(),
76 db: Data {
77 server_signingkeys: args.db["server_signingkeys"].clone(),
78 },
79 }))
80 }
81
82 fn name(&self) -> &str { crate::service::make_name(std::module_path!()) }
83}
84
85#[implement(Service)]
90#[inline]
91#[must_use]
92pub fn keypair(&self) -> &Ed25519KeyPair { &self.keypair }
93
94#[implement(Service)]
99#[inline]
100#[must_use]
101pub fn active_key_id(&self) -> &ServerSigningKeyId { self.active_verify_key().0 }
102
103#[implement(Service)]
108#[inline]
109#[must_use]
110pub fn active_verify_key(&self) -> (&ServerSigningKeyId, &VerifyKey) {
111 debug_assert!(self.verify_keys.len() <= 1, "more than one active verify_key");
112 self.verify_keys
113 .iter()
114 .next()
115 .map(|(id, key)| (id.as_ref(), key))
116 .expect("missing active verify_key")
117}
118
119#[implement(Service)]
125async fn add_signing_keys(&self, new_keys: ServerSigningKeys) {
126 let origin = &new_keys.server_name;
127
128 let mut keys: ServerSigningKeys = self
130 .db
131 .server_signingkeys
132 .get(origin)
133 .await
134 .deserialized()
135 .unwrap_or_else(|_| {
136 ServerSigningKeys::new(origin.to_owned(), MilliSecondsSinceUnixEpoch::now())
138 });
139
140 keys.verify_keys.extend(new_keys.verify_keys);
141 keys.old_verify_keys
142 .extend(new_keys.old_verify_keys);
143
144 self.db
145 .server_signingkeys
146 .raw_put(origin, Json(&keys));
147}
148
149#[implement(Service)]
154pub async fn required_keys_exist(
155 &self,
156 object: &CanonicalJsonObject,
157 rules: &RoomVersionRules,
158) -> bool {
159 use ruma::signatures::required_keys;
160
161 let Ok(required_keys) = required_keys(object, &rules.signatures) else {
162 return false;
163 };
164
165 required_keys
166 .iter()
167 .flat_map(|(server, key_ids)| key_ids.iter().map(move |key_id| (server, key_id)))
168 .stream()
169 .all(|(server, key_id)| self.verify_key_exists(server, key_id))
170 .await
171}
172
173#[implement(Service)]
178pub async fn verify_key_exists(&self, origin: &ServerName, key_id: &ServerSigningKeyId) -> bool {
179 type KeysMap<'a> = BTreeMap<&'a ServerSigningKeyId, &'a RawJsonValue>;
180
181 let Ok(keys) = self
182 .db
183 .server_signingkeys
184 .get(origin)
185 .await
186 .deserialized::<Raw<ServerSigningKeys>>()
187 else {
188 return false;
189 };
190
191 if let Ok(Some(verify_keys)) = keys.get_field::<KeysMap<'_>>("verify_keys")
192 && verify_keys.contains_key(key_id)
193 {
194 return true;
195 }
196
197 if let Ok(Some(old_verify_keys)) = keys.get_field::<KeysMap<'_>>("old_verify_keys")
198 && old_verify_keys.contains_key(key_id)
199 {
200 return true;
201 }
202
203 false
204}
205
206#[implement(Service)]
211pub async fn verify_keys_for(&self, origin: &ServerName) -> VerifyKeys {
212 let mut keys = self
213 .signing_keys_for(origin)
214 .await
215 .map(|keys| merge_old_keys(keys).verify_keys)
216 .unwrap_or(BTreeMap::new());
217
218 if self.services.globals.server_is_ours(origin) {
219 keys.extend(self.verify_keys.clone());
220 }
221
222 keys
223}
224
225#[implement(Service)]
231pub async fn signing_keys_for(&self, origin: &ServerName) -> Result<ServerSigningKeys> {
232 self.db
233 .server_signingkeys
234 .get(origin)
235 .await
236 .deserialized()
237}
238
239#[implement(Service)]
240fn minimum_valid_ts(&self) -> MilliSecondsSinceUnixEpoch {
241 let timepoint =
242 timepoint_from_now(self.minimum_valid).expect("SystemTime should not overflow");
243
244 MilliSecondsSinceUnixEpoch::from_system_time(timepoint).expect("UInt should not overflow")
245}
246
247fn merge_old_keys(mut keys: ServerSigningKeys) -> ServerSigningKeys {
248 keys.verify_keys.extend(
249 keys.old_verify_keys
250 .clone()
251 .into_iter()
252 .map(|(key_id, old)| (key_id, VerifyKey::new(old.key))),
253 );
254
255 keys
256}
257
258fn extract_key(mut keys: ServerSigningKeys, key_id: &ServerSigningKeyId) -> Option<VerifyKey> {
259 keys.verify_keys.remove(key_id).or_else(|| {
260 keys.old_verify_keys
261 .remove(key_id)
262 .map(|old| VerifyKey::new(old.key))
263 })
264}
265
266fn key_exists(keys: &ServerSigningKeys, key_id: &ServerSigningKeyId) -> bool {
267 keys.verify_keys.contains_key(key_id) || keys.old_verify_keys.contains_key(key_id)
268}