parsec_interface/operations/
psa_sign_message.rs

1// Copyright 2021 Contributors to the Parsec project.
2// SPDX-License-Identifier: Apache-2.0
3//! # PsaSignMessage operation
4//!
5//! Sign a message with a private key.
6
7use super::psa_key_attributes::Attributes;
8use crate::operations::psa_algorithm::AsymmetricSignature;
9
10/// Native object for asymmetric sign operations.
11#[derive(Debug)]
12pub struct Operation {
13    /// Defines which key should be used for the signing operation.
14    pub key_name: String,
15    /// An asymmetric signature algorithm that separates the hash and sign operations, that is
16    /// compatible with the type of key.
17    pub alg: AsymmetricSignature,
18    /// The message to sign.
19    pub message: zeroize::Zeroizing<Vec<u8>>,
20}
21
22/// Native object for asymmetric sign result.
23#[derive(Debug)]
24pub struct Result {
25    /// The `signature` field contains the resulting bytes from the signing operation. The format of
26    /// the signature is as specified by the provider doing the signing.
27    pub signature: zeroize::Zeroizing<Vec<u8>>,
28}
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 signing messages
35    /// * the key policy allows the signing 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_sign_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_sign_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        })
80        .validate(get_attrs())
81        .unwrap();
82    }
83
84    #[test]
85    fn cannot_sign() {
86        let mut attrs = get_attrs();
87        attrs.policy.usage_flags = UsageFlags::default();
88        assert_eq!(
89            (Operation {
90                key_name: String::from("some key"),
91                alg: AsymmetricSignature::Ecdsa {
92                    hash_alg: Hash::Sha256.into(),
93                },
94                message: vec![0xff; 32].into(),
95            })
96            .validate(attrs)
97            .unwrap_err(),
98            ResponseStatus::PsaErrorNotPermitted
99        );
100    }
101
102    #[test]
103    fn wrong_algorithm() {
104        assert_eq!(
105            (Operation {
106                key_name: String::from("some key"),
107                alg: AsymmetricSignature::Ecdsa {
108                    hash_alg: Hash::Sha224.into(),
109                },
110                message: vec![0xff; 28].into(),
111            })
112            .validate(get_attrs())
113            .unwrap_err(),
114            ResponseStatus::PsaErrorNotPermitted
115        );
116    }
117
118    #[test]
119    fn wrong_scheme() {
120        assert_eq!(
121            (Operation {
122                key_name: String::from("some key"),
123                alg: AsymmetricSignature::RsaPss {
124                    hash_alg: Hash::Sha224.into(),
125                },
126                message: vec![0xff; 28].into(),
127            })
128            .validate(get_attrs())
129            .unwrap_err(),
130            ResponseStatus::PsaErrorNotPermitted
131        );
132    }
133}