tuwunel_service/oauth/server/
signing_key.rs1use aws_lc_rs::signature::{self, EcdsaKeyPair};
2use serde::{Deserialize, Serialize};
3use tuwunel_core::{Result, at, err, info, result::AndThenRef, utils};
4use tuwunel_database::{Cbor, Deserialized};
5
6use super::Data;
7
8#[derive(Deserialize, Serialize)]
9pub(super) struct SigningKey {
10 pub(super) key_id: String,
11 pub(super) key_der: Vec<u8>,
12}
13
14const SIGNING_KEY_DB_KEY: &str = "oidc_signing_key";
15
16pub(super) fn init_signing_key(db: &Data) -> Result<SigningKey> {
17 if let Ok(signing_key_data) = db
18 .oidc_signingkey
19 .get_blocking(SIGNING_KEY_DB_KEY)
20 .and_then(|val| val.deserialized::<Cbor<SigningKey>>())
21 .map(at!(0))
22 {
23 info!(
24 key_id = ?signing_key_data.key_id,
25 "Loaded existing OIDC signing key",
26 );
27
28 return Ok(signing_key_data);
29 }
30
31 let signing_key_data = generate_signing_key()?;
32
33 db.oidc_signingkey
34 .raw_put(SIGNING_KEY_DB_KEY, Cbor(&signing_key_data));
35
36 info!(
37 key_id = ?signing_key_data.key_id,
38 "Generated new OIDC signing key",
39 );
40
41 Ok(signing_key_data)
42}
43
44fn generate_signing_key() -> Result<SigningKey> {
45 let alg = &signature::ECDSA_P256_SHA256_FIXED_SIGNING;
46 let key_id = utils::random_string(16);
47 let pkcs8 = EcdsaKeyPair::generate(alg)
48 .and_then_ref(EcdsaKeyPair::to_pkcs8v1)
49 .map_err(|e| err!(error!("Failed to generate ECDSA key: {e}")))?;
50
51 Ok(SigningKey { key_der: pkcs8.as_ref().to_vec(), key_id })
52}