Skip to main content

tuwunel_service/oauth/server/
signing_key.rs

1use 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}