aws_lc_rs/pqdsa/
signature.rs

1// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// SPDX-License-Identifier: Apache-2.0 OR ISC
3
4use crate::aws_lc::EVP_PKEY;
5use crate::buffer::Buffer;
6use crate::encoding::{AsDer, PublicKeyX509Der};
7use crate::error::Unspecified;
8use crate::evp_pkey::No_EVP_PKEY_CTX_consumer;
9use crate::pqdsa::{parse_pqdsa_public_key, AlgorithmID};
10use crate::ptr::LcPtr;
11use crate::sealed;
12use crate::signature::VerificationAlgorithm;
13use core::fmt;
14use core::fmt::{Debug, Formatter};
15#[cfg(feature = "ring-sig-verify")]
16use untrusted::Input;
17
18/// An PQDSA verification algorithm.
19#[derive(Debug, Eq, PartialEq)]
20pub struct PqdsaVerificationAlgorithm {
21    pub(crate) id: &'static AlgorithmID,
22}
23
24impl sealed::Sealed for PqdsaVerificationAlgorithm {}
25
26/// An PQDSA signing algorithm.
27#[derive(Debug, Eq, PartialEq)]
28pub struct PqdsaSigningAlgorithm(pub(crate) &'static PqdsaVerificationAlgorithm);
29
30impl PqdsaSigningAlgorithm {
31    /// Returns the size of the signature in bytes.
32    #[must_use]
33    pub fn signature_len(&self) -> usize {
34        self.0.id.signature_size_bytes()
35    }
36}
37
38/// A PQDSA public key.
39#[derive(Clone)]
40pub struct PublicKey {
41    evp_pkey: LcPtr<EVP_PKEY>,
42    pub(crate) octets: Box<[u8]>,
43}
44unsafe impl Send for PublicKey {}
45
46unsafe impl Sync for PublicKey {}
47
48impl PublicKey {
49    pub(crate) fn from_private_evp_pkey(evp_pkey: &LcPtr<EVP_PKEY>) -> Result<Self, Unspecified> {
50        let octets = evp_pkey.as_const().marshal_raw_public_key()?;
51        Ok(Self {
52            evp_pkey: evp_pkey.clone(),
53            octets: octets.into_boxed_slice(),
54        })
55    }
56}
57
58impl VerificationAlgorithm for PqdsaVerificationAlgorithm {
59    /// Verifies the the signature of `msg` using the public key `public_key`.
60    ///
61    /// # Errors
62    /// `error::Unspecified` if the signature is invalid.
63    #[cfg(feature = "ring-sig-verify")]
64    fn verify(
65        &self,
66        public_key: Input<'_>,
67        msg: Input<'_>,
68        signature: Input<'_>,
69    ) -> Result<(), Unspecified> {
70        self.verify_sig(
71            public_key.as_slice_less_safe(),
72            msg.as_slice_less_safe(),
73            signature.as_slice_less_safe(),
74        )
75    }
76
77    /// Verifies the signature for `msg` using the `public_key`.
78    ///
79    /// # Errors
80    /// `error::Unspecified` if the signature is invalid.
81    fn verify_sig(
82        &self,
83        public_key: &[u8],
84        msg: &[u8],
85        signature: &[u8],
86    ) -> Result<(), Unspecified> {
87        let evp_pkey = parse_pqdsa_public_key(public_key, self.id)?;
88
89        evp_pkey.verify(msg, None, No_EVP_PKEY_CTX_consumer, signature)
90    }
91}
92
93impl AsRef<[u8]> for PublicKey {
94    /// Serializes the public key as a raw byte string.
95    fn as_ref(&self) -> &[u8] {
96        self.octets.as_ref()
97    }
98}
99
100impl AsDer<PublicKeyX509Der<'static>> for PublicKey {
101    /// Provides the public key as a DER-encoded (X.509) `SubjectPublicKeyInfo` structure.
102    /// # Errors
103    /// Returns an error if the public key fails to marshal to X.509.
104    fn as_der(&self) -> Result<PublicKeyX509Der<'static>, crate::error::Unspecified> {
105        let der = self.evp_pkey.as_const().marshal_rfc5280_public_key()?;
106        Ok(PublicKeyX509Der::from(Buffer::new(der)))
107    }
108}
109
110impl Debug for PublicKey {
111    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
112        f.write_str(&format!(
113            "PqdsaPublicKey(\"{}\")",
114            crate::hex::encode(self.octets.as_ref())
115        ))
116    }
117}