parsec_interface/operations/
psa_verify_message.rs

1// Copyright 2021 Contributors to the Parsec project.
2// SPDX-License-Identifier: Apache-2.0
3//! # PsaVerifyMessage operation
4//!
5//! Verify the signature of a message using a public key.
6use super::psa_key_attributes::Attributes;
7use crate::operations::psa_algorithm::AsymmetricSignature;
8
9/// Native object for asymmetric verification of signatures.
10#[derive(Debug)]
11pub struct Operation {
12    /// `key_name` specifies the key to be used for verification.
13    pub key_name: String,
14    /// An asymmetric signature algorithm that separates the hash and sign operations, that is
15    /// compatible with the type of key.
16    pub alg: AsymmetricSignature,
17    /// The `message` whose signature is to be verified for the
18    /// asymmetric signing operation.
19    pub message: zeroize::Zeroizing<Vec<u8>>,
20    /// Buffer containing the signature to verify.
21    pub signature: zeroize::Zeroizing<Vec<u8>>,
22}
23
24/// Native object for asymmetric verification of signatures.
25///
26/// The true result of the operation is sent as a `status` code in the response.
27#[derive(Copy, Clone, Debug)]
28pub struct Result;
29
30impl Operation {
31    /// Validate the contents of the operation against the attributes of the key it targets
32    ///
33    /// This method checks that:
34    /// * the key policy allows verifying signatures on messages
35    /// * the key policy allows the verification algorithm requested in the operation
36    /// * the key type is compatible with the requested algorithm
37    pub fn validate(&self, key_attributes: Attributes) -> crate::requests::Result<()> {
38        key_attributes.can_verify_message()?;
39        key_attributes.permits_alg(self.alg.into())?;
40        key_attributes.compatible_with_alg(self.alg.into())?;
41
42        Ok(())
43    }
44}
45
46#[cfg(test)]
47mod tests {
48    use super::*;
49    use crate::operations::psa_algorithm::{Algorithm, AsymmetricSignature, Hash};
50    use crate::operations::psa_key_attributes::{EccFamily, Lifetime, Policy, Type, UsageFlags};
51    use crate::requests::ResponseStatus;
52
53    fn get_attrs() -> Attributes {
54        let mut usage_flags = UsageFlags::default();
55        let _ = usage_flags.set_verify_hash();
56        Attributes {
57            lifetime: Lifetime::Persistent,
58            key_type: Type::EccKeyPair {
59                curve_family: EccFamily::SecpR1,
60            },
61            bits: 256,
62            policy: Policy {
63                usage_flags,
64                permitted_algorithms: Algorithm::AsymmetricSignature(AsymmetricSignature::Ecdsa {
65                    hash_alg: Hash::Sha256.into(),
66                }),
67            },
68        }
69    }
70
71    #[test]
72    fn validate_success() {
73        (Operation {
74            key_name: String::from("some key"),
75            alg: AsymmetricSignature::Ecdsa {
76                hash_alg: Hash::Sha256.into(),
77            },
78            message: vec![0xff; 32].into(),
79            signature: vec![0xa5; 65].into(),
80        })
81        .validate(get_attrs())
82        .unwrap();
83    }
84
85    #[test]
86    fn cannot_sign() {
87        let mut attrs = get_attrs();
88        attrs.policy.usage_flags = UsageFlags::default();
89        assert_eq!(
90            (Operation {
91                key_name: String::from("some key"),
92                alg: AsymmetricSignature::Ecdsa {
93                    hash_alg: Hash::Sha256.into(),
94                },
95                message: vec![0xff; 32].into(),
96                signature: vec![0xa5; 65].into(),
97            })
98            .validate(attrs)
99            .unwrap_err(),
100            ResponseStatus::PsaErrorNotPermitted
101        );
102    }
103
104    #[test]
105    fn wrong_algorithm() {
106        assert_eq!(
107            (Operation {
108                key_name: String::from("some key"),
109                alg: AsymmetricSignature::Ecdsa {
110                    hash_alg: Hash::Sha224.into(),
111                },
112                message: vec![0xff; 28].into(),
113                signature: vec![0xa5; 65].into(),
114            })
115            .validate(get_attrs())
116            .unwrap_err(),
117            ResponseStatus::PsaErrorNotPermitted
118        );
119    }
120
121    #[test]
122    fn wrong_scheme() {
123        assert_eq!(
124            (Operation {
125                key_name: String::from("some key"),
126                alg: AsymmetricSignature::RsaPss {
127                    hash_alg: Hash::Sha224.into(),
128                },
129                message: vec![0xff; 28].into(),
130                signature: vec![0xa5; 65].into(),
131            })
132            .validate(get_attrs())
133            .unwrap_err(),
134            ResponseStatus::PsaErrorNotPermitted
135        );
136    }
137}