summaryrefslogtreecommitdiffhomepage
path: root/mullvad-update/src
diff options
context:
space:
mode:
authorDavid Lönnhager <david.l@mullvad.net>2025-04-02 13:49:15 +0200
committerDavid Lönnhager <david.l@mullvad.net>2025-04-03 14:10:58 +0200
commit3d03dc779f6829a236d139543e3c19fa56c4a25e (patch)
tree63656e7a74de1ee9ec416b23a80ec42c53dc304d /mullvad-update/src
parent00e26c1d17fb9044f8cbc0a168eab1edef70ba8a (diff)
downloadmullvadvpn-3d03dc779f6829a236d139543e3c19fa56c4a25e.tar.xz
mullvadvpn-3d03dc779f6829a236d139543e3c19fa56c4a25e.zip
Set default pubkeys and pinned certificate in mullvad-update
Diffstat (limited to 'mullvad-update/src')
-rw-r--r--mullvad-update/src/client/api.rs12
-rw-r--r--mullvad-update/src/format/deserializer.rs15
-rw-r--r--mullvad-update/src/keys.rs6
-rw-r--r--mullvad-update/src/lib.rs3
4 files changed, 35 insertions, 1 deletions
diff --git a/mullvad-update/src/client/api.rs b/mullvad-update/src/client/api.rs
index 7811dee275..05c8359449 100644
--- a/mullvad-update/src/client/api.rs
+++ b/mullvad-update/src/client/api.rs
@@ -35,6 +35,18 @@ impl HttpVersionInfoProvider {
/// Maximum size of the GET response, in bytes
const SIZE_LIMIT: usize = 1024 * 1024;
+ /// Construct an [HttpVersionInfoProvider] for `url` using reasonable defaults.
+ ///
+ /// By default, `pinned_certificate` will be set to the LE root certificate, and
+ /// `verifying_keys` will be set to the keys in `trusted-metadata-signing-keys`.
+ pub fn new(url: String) -> Self {
+ HttpVersionInfoProvider {
+ url,
+ pinned_certificate: Some(crate::keys::PINNED_CERTIFICATE.clone()),
+ verifying_keys: crate::keys::TRUSTED_METADATA_SIGNING_PUBKEYS.clone(),
+ }
+ }
+
/// Download and verify signed data
pub async fn get_versions(
&self,
diff --git a/mullvad-update/src/format/deserializer.rs b/mullvad-update/src/format/deserializer.rs
index 980fd52ca6..8b138578b5 100644
--- a/mullvad-update/src/format/deserializer.rs
+++ b/mullvad-update/src/format/deserializer.rs
@@ -10,6 +10,21 @@ use super::{PartialSignedResponse, ResponseSignature, SignedResponse};
impl SignedResponse {
/// Deserialize some bytes to JSON, and verify them, including signature and expiry.
/// If successful, the deserialized data is returned.
+ ///
+ /// This uses the keys in `trusted-metadata-signing-pubkeys`
+ pub fn deserialize_and_verify(
+ bytes: &[u8],
+ min_metadata_version: usize,
+ ) -> Result<Self, anyhow::Error> {
+ Self::deserialize_and_verify_with_keys(
+ &crate::keys::TRUSTED_METADATA_SIGNING_PUBKEYS,
+ bytes,
+ min_metadata_version,
+ )
+ }
+
+ /// Deserialize some bytes to JSON, and verify them, including signature and expiry.
+ /// If successful, the deserialized data is returned.
pub fn deserialize_and_verify_with_keys(
keys: &Vec1<VerifyingKey>,
bytes: &[u8],
diff --git a/mullvad-update/src/keys.rs b/mullvad-update/src/keys.rs
index 9b0abf5c6b..73ca8519d0 100644
--- a/mullvad-update/src/keys.rs
+++ b/mullvad-update/src/keys.rs
@@ -4,6 +4,12 @@ use crate::format::key::VerifyingKey;
use std::sync::LazyLock;
use vec1::Vec1;
+/// Default TLS certificate to pin to
+pub static PINNED_CERTIFICATE: LazyLock<reqwest::Certificate> = LazyLock::new(|| {
+ const CERT_BYTES: &[u8] = include_bytes!("../../mullvad-api/le_root_cert.pem");
+ reqwest::Certificate::from_pem(CERT_BYTES).expect("invalid cert")
+});
+
/// Pubkeys used to verify metadata from the Mullvad API (production)
pub static TRUSTED_METADATA_SIGNING_PUBKEYS: LazyLock<Vec1<VerifyingKey>> =
LazyLock::new(|| parse_keys(include_str!("../trusted-metadata-signing-pubkeys")));
diff --git a/mullvad-update/src/lib.rs b/mullvad-update/src/lib.rs
index 88e78034a7..eb9877f62f 100644
--- a/mullvad-update/src/lib.rs
+++ b/mullvad-update/src/lib.rs
@@ -6,7 +6,8 @@ mod client;
#[cfg(feature = "client")]
pub use client::*;
-pub mod keys;
+#[cfg(feature = "client")]
+mod keys;
pub mod version;