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