tuwunel_service/server_keys/
mod.rs1mod 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 let mut keys: ServerSigningKeys = self
91 .db
92 .server_signingkeys
93 .get(origin)
94 .await
95 .deserialized()
96 .unwrap_or_else(|_| {
97 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}