twizzler_security/keys/
verify.rs

1#[cfg(feature = "log")]
2use log::{debug, error};
3use p256::{
4    ecdsa::{
5        signature::Verifier, Signature as EcdsaSignature, SigningKey as EcdsaSigningKey,
6        VerifyingKey as EcdsaVerifyingKey,
7    },
8    elliptic_curve::sec1::EncodedPoint,
9    NistP256,
10};
11#[cfg(feature = "user")]
12use twizzler::marker::BaseType;
13
14use super::{KeyBuffer, Signature, SigningKey};
15use crate::{SecurityError, SigningScheme};
16
17// making our own struct for verifying key since we need to be able to support keys with different
18// schemes, (meaning they could also be different lengths)
19/// An Objects `SigningKey`, used to create an Object.
20/// Is also reffered to as an Objects' `kuid`. The kernel uses this key to verify any `Cap`s or
21/// `Del`s. Is agnostic over SigningSchemes.
22#[derive(Clone, Debug, PartialEq, Eq)]
23pub struct VerifyingKey {
24    /// The buffer that stores the raw key bytes.
25    key: KeyBuffer,
26    /// The signing scheme of this key
27    pub scheme: SigningScheme,
28}
29
30impl VerifyingKey {
31    /// Create a VerifyingKey via a `SigningKey`, and `SigningScheme`.
32    pub fn new(
33        scheme: &SigningScheme,
34        target_private_key: &SigningKey,
35    ) -> Result<Self, SecurityError> {
36        #[cfg(feature = "log")]
37        debug!("Creating new verifying key with scheme: {:?}", scheme);
38        match scheme {
39            SigningScheme::Ecdsa => {
40                let vkey = EcdsaVerifyingKey::from(TryInto::<EcdsaSigningKey>::try_into(
41                    target_private_key,
42                )?);
43
44                let point = vkey.to_encoded_point(false);
45                let bytes = point.as_bytes();
46
47                let key = KeyBuffer::from_slice(bytes).expect(
48                    "A ECDSA Verifying Key cannot fit within the currently configured MAX_KEY_SIZE",
49                );
50
51                Ok(VerifyingKey {
52                    key,
53                    scheme: SigningScheme::Ecdsa,
54                })
55            }
56        }
57    }
58
59    /// Parse a VerifyingKey out of a slice and a `SigningScheme`
60    pub fn from_slice(slice: &[u8], scheme: SigningScheme) -> Result<Self, SecurityError> {
61        match scheme {
62            SigningScheme::Ecdsa => {
63                let point: EncodedPoint<NistP256> = EncodedPoint::<NistP256>::from_bytes(slice)
64                    .map_err(|_e| {
65                        #[cfg(feature = "log")]
66                        error!(
67                            "Unable to create an encoded point from bytes due to :{:?}",
68                            _e
69                        );
70
71                        SecurityError::InvalidKey
72                    })?;
73
74                // we create key here to ensure its valid
75                let key = EcdsaVerifyingKey::from_encoded_point(&point).map_err(|_e| {
76                    #[cfg(feature = "log")]
77                    error!(
78                        "Unable to create an EcdsaVerifyingKey from encoded point, due to :{:?}",
79                        _e
80                    );
81
82                    SecurityError::InvalidKey
83                })?;
84
85                Ok(key.into())
86            }
87        }
88    }
89
90    /// A byte-slice representation of this VerifyingKey.
91    pub fn as_bytes(&self) -> &[u8] {
92        &self.key
93    }
94
95    /// Checks whether or not the `signature` is valid.
96    pub fn verify(&self, msg: &[u8], signature: &Signature) -> Result<(), SecurityError> {
97        match self.scheme {
98            SigningScheme::Ecdsa => {
99                let key: EcdsaVerifyingKey = self.try_into()?;
100                let ecdsa_sig: EcdsaSignature = signature.try_into()?;
101                key.verify(msg, &ecdsa_sig).map_err(|_e| {
102                    #[cfg(feature = "log")]
103                    error!("Failed verification of signature due to: {:#?}", _e);
104
105                    SecurityError::SignatureMismatch
106                })
107            }
108        }
109    }
110}
111
112impl TryFrom<&VerifyingKey> for EcdsaVerifyingKey {
113    type Error = SecurityError;
114    fn try_from(value: &VerifyingKey) -> Result<Self, Self::Error> {
115        let point: EncodedPoint<NistP256> = EncodedPoint::<NistP256>::from_bytes(value.as_bytes())
116            .map_err(|_e| {
117                #[cfg(feature = "log")]
118                error!(
119                    "Failed to create an encoded point from bytes due to :{:#?}",
120                    _e
121                );
122
123                SecurityError::InvalidKey
124            })?;
125
126        let key = EcdsaVerifyingKey::from_encoded_point(&point).map_err(|_e| {
127            #[cfg(feature = "log")]
128            error!(
129                "Failed to create a EcdsaVerifyingKey out of an encoded point due to :{:#?}",
130                _e
131            );
132
133            SecurityError::InvalidKey
134        })?;
135
136        Ok(key)
137    }
138}
139
140impl From<EcdsaVerifyingKey> for VerifyingKey {
141    fn from(value: EcdsaVerifyingKey) -> Self {
142        let point = value.to_encoded_point(false);
143
144        let key = KeyBuffer::from_slice(point.as_bytes()).expect(
145            "A ECDSA Verifying Key cannot fit within the currently configured MAX_KEY_SIZE",
146        );
147
148        VerifyingKey {
149            key,
150            scheme: SigningScheme::Ecdsa,
151        }
152    }
153}
154
155#[cfg(feature = "user")]
156impl BaseType for VerifyingKey {
157    fn fingerprint() -> u64 {
158        return 6;
159    }
160}