Skip to main content

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::digest::Digest;
7use crate::encoding::{AsDer, PublicKeyX509Der};
8use crate::error::Unspecified;
9use crate::evp_pkey::No_EVP_PKEY_CTX_consumer;
10use crate::pqdsa::{parse_pqdsa_public_key, AlgorithmID};
11use crate::ptr::LcPtr;
12use crate::signature::{ParsedPublicKey, ParsedVerificationAlgorithm, VerificationAlgorithm};
13use crate::{digest, sealed};
14use core::fmt;
15use core::fmt::{Debug, Formatter};
16#[cfg(feature = "ring-sig-verify")]
17use untrusted::Input;
18
19/// An PQDSA verification algorithm.
20#[derive(Debug, Eq, PartialEq)]
21pub struct PqdsaVerificationAlgorithm {
22    pub(crate) id: &'static AlgorithmID,
23}
24
25impl sealed::Sealed for PqdsaVerificationAlgorithm {}
26
27/// An PQDSA signing algorithm.
28#[derive(Debug, Eq, PartialEq)]
29pub struct PqdsaSigningAlgorithm(pub(crate) &'static PqdsaVerificationAlgorithm);
30
31impl PqdsaSigningAlgorithm {
32    /// Returns the size of the signature in bytes.
33    #[must_use]
34    pub fn signature_len(&self) -> usize {
35        self.0.id.signature_size_bytes()
36    }
37}
38
39/// A PQDSA public key.
40#[derive(Clone)]
41pub struct PublicKey {
42    evp_pkey: LcPtr<EVP_PKEY>,
43    pub(crate) octets: Box<[u8]>,
44}
45unsafe impl Send for PublicKey {}
46
47unsafe impl Sync for PublicKey {}
48
49impl PublicKey {
50    pub(crate) fn from_private_evp_pkey(evp_pkey: &LcPtr<EVP_PKEY>) -> Result<Self, Unspecified> {
51        let octets = evp_pkey.as_const().marshal_raw_public_key()?;
52        Ok(Self {
53            evp_pkey: evp_pkey.clone(),
54            octets: octets.into_boxed_slice(),
55        })
56    }
57}
58
59impl ParsedVerificationAlgorithm for PqdsaVerificationAlgorithm {
60    fn parsed_verify_sig(
61        &self,
62        public_key: &ParsedPublicKey,
63        msg: &[u8],
64        signature: &[u8],
65    ) -> Result<(), Unspecified> {
66        let evp_pkey = public_key.key();
67        evp_pkey.verify(msg, None, No_EVP_PKEY_CTX_consumer, signature)
68    }
69
70    fn parsed_verify_digest_sig(
71        &self,
72        public_key: &ParsedPublicKey,
73        digest: &Digest,
74        signature: &[u8],
75    ) -> Result<(), Unspecified> {
76        let evp_pkey = public_key.key();
77        evp_pkey.verify_digest_sig(digest, No_EVP_PKEY_CTX_consumer, signature)
78    }
79}
80
81impl VerificationAlgorithm for PqdsaVerificationAlgorithm {
82    /// Verifies the the signature of `msg` using the public key `public_key`.
83    ///
84    /// # Errors
85    /// `error::Unspecified` if the signature is invalid.
86    #[cfg(feature = "ring-sig-verify")]
87    fn verify(
88        &self,
89        public_key: Input<'_>,
90        msg: Input<'_>,
91        signature: Input<'_>,
92    ) -> Result<(), Unspecified> {
93        self.verify_sig(
94            public_key.as_slice_less_safe(),
95            msg.as_slice_less_safe(),
96            signature.as_slice_less_safe(),
97        )
98    }
99
100    /// Verifies the signature for `msg` using the `public_key`.
101    ///
102    /// # Errors
103    /// `error::Unspecified` if the signature is invalid.
104    fn verify_sig(
105        &self,
106        public_key: &[u8],
107        msg: &[u8],
108        signature: &[u8],
109    ) -> Result<(), Unspecified> {
110        let evp_pkey = parse_pqdsa_public_key(public_key, self.id)?;
111
112        evp_pkey.verify(msg, None, No_EVP_PKEY_CTX_consumer, signature)
113    }
114
115    /// DO NOT USE. This function is required by `VerificationAlgorithm` but cannot be used w/ Ed25519.
116    ///
117    /// # Errors
118    /// Always returns `Unspecified`.
119    fn verify_digest_sig(
120        &self,
121        _public_key: &[u8],
122        _digest: &digest::Digest,
123        _signature: &[u8],
124    ) -> Result<(), Unspecified> {
125        Err(Unspecified)
126    }
127}
128
129impl AsRef<[u8]> for PublicKey {
130    /// Serializes the public key as a raw byte string.
131    fn as_ref(&self) -> &[u8] {
132        self.octets.as_ref()
133    }
134}
135
136impl AsDer<PublicKeyX509Der<'static>> for PublicKey {
137    /// Provides the public key as a DER-encoded (X.509) `SubjectPublicKeyInfo` structure.
138    /// # Errors
139    /// Returns an error if the public key fails to marshal to X.509.
140    fn as_der(&self) -> Result<PublicKeyX509Der<'static>, crate::error::Unspecified> {
141        let der = self.evp_pkey.as_const().marshal_rfc5280_public_key()?;
142        Ok(PublicKeyX509Der::from(Buffer::new(der)))
143    }
144}
145
146impl Debug for PublicKey {
147    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
148        f.write_str(&format!(
149            "PqdsaPublicKey(\"{}\")",
150            crate::hex::encode(self.octets.as_ref())
151        ))
152    }
153}