Skip to main content

mz_ccsr/
tls.rs

1// Copyright Materialize, Inc. and contributors. All rights reserved.
2//
3// Use of this software is governed by the Business Source License
4// included in the LICENSE file.
5//
6// As of the Change Date specified in that file, in accordance with
7// the Business Source License, use of this software will be governed
8// by the Apache License, Version 2.0.
9
10//! TLS certificates and identities.
11
12use serde::{Deserialize, Serialize};
13
14use mz_tls_util::pkcs12der_from_pem;
15use zeroize::Zeroize;
16
17/// A [Serde][serde]-enabled wrapper around [`reqwest::Identity`].
18///
19/// [Serde]: serde
20#[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
21pub struct Identity {
22    der: Vec<u8>,
23    pass: String,
24}
25
26impl Zeroize for Identity {
27    fn zeroize(&mut self) {
28        self.der.zeroize();
29        self.pass.zeroize();
30    }
31}
32
33impl Drop for Identity {
34    fn drop(&mut self) {
35        self.zeroize();
36    }
37}
38
39impl Identity {
40    /// Constructs an identity from a PEM-formatted key and certificate using OpenSSL.
41    pub fn from_pem(key: &[u8], cert: &[u8]) -> Result<Self, openssl::error::ErrorStack> {
42        let (der, pass) = pkcs12der_from_pem(key, cert)?.into_parts();
43        Ok(Identity { der, pass })
44    }
45
46    /// Wraps [`reqwest::Identity::from_pkcs12_der`].
47    pub fn from_pkcs12_der(der: Vec<u8>, pass: String) -> Result<Self, reqwest::Error> {
48        let _ = reqwest::Identity::from_pkcs12_der(&der, &pass)?;
49        Ok(Identity { der, pass })
50    }
51}
52
53impl From<Identity> for reqwest::Identity {
54    fn from(id: Identity) -> Self {
55        reqwest::Identity::from_pkcs12_der(&id.der, &id.pass).expect("known to be a valid identity")
56    }
57}
58
59/// A [Serde][serde]-enabled wrapper around [`reqwest::Certificate`].
60///
61/// [Serde]: serde
62#[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
63pub struct Certificate {
64    der: Vec<u8>,
65}
66
67impl Certificate {
68    /// Wraps [`reqwest::Certificate::from_pem`].
69    pub fn from_pem(pem: &[u8]) -> native_tls::Result<Certificate> {
70        Ok(Certificate {
71            der: native_tls::Certificate::from_pem(pem)?.to_der()?,
72        })
73    }
74
75    /// Wraps [`reqwest::Certificate::from_der`].
76    pub fn from_der(der: &[u8]) -> native_tls::Result<Certificate> {
77        let _ = native_tls::Certificate::from_der(der)?;
78        Ok(Certificate { der: der.into() })
79    }
80}
81
82impl From<Certificate> for reqwest::Certificate {
83    fn from(cert: Certificate) -> Self {
84        reqwest::Certificate::from_der(&cert.der).expect("known to be a valid cert")
85    }
86}