| // Copyright 2026 The BoringSSL Authors | |
| // | |
| // Licensed under the Apache License, Version 2.0 (the "License"); | |
| // you may not use this file except in compliance with the License. | |
| // You may obtain a copy of the License at | |
| // | |
| // https://www.apache.org/licenses/LICENSE-2.0 | |
| // | |
| // Unless required by applicable law or agreed to in writing, software | |
| // distributed under the License is distributed on an "AS IS" BASIS, | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| // See the License for the specific language governing permissions and | |
| // limitations under the License. | |
| use alloc::{boxed::Box, vec::Vec}; | |
| use core::{ | |
| fmt::{Debug, Formatter, Result as FmtResult}, | |
| marker::PhantomData, | |
| }; | |
| use bssl_crypto::{digest, ec, ecdsa, ed25519, rsa}; | |
| use rustls::{ | |
| Error, SignatureAlgorithm, SignatureScheme, | |
| pki_types::{PrivatePkcs1KeyDer, PrivateSec1KeyDer}, | |
| sign::{Signer, SigningKey}, | |
| }; | |
| use crate::{RsaSignatureDigest, pki}; | |
| /// A generic `id-rsaEncryption` RSA key | |
| /// | |
| /// This key type is only intended for signature | |
| pub(crate) struct RsaPrivateKey(pub rsa::PrivateKey); | |
| impl TryFrom<PrivatePkcs1KeyDer<'_>> for RsaPrivateKey { | |
| type Error = Error; | |
| fn try_from(der: PrivatePkcs1KeyDer) -> Result<Self, Self::Error> { | |
| let der = der.secret_pkcs1_der(); | |
| let key = rsa::PrivateKey::from_der_rsa_private_key(der) | |
| .ok_or(Error::General("Cannot parse PKCS#1 key from DER".into()))?; | |
| Ok(Self(key)) | |
| } | |
| } | |
| impl Debug for RsaPrivateKey { | |
| fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { | |
| f.debug_tuple("RsaPrivateKey").finish() | |
| } | |
| } | |
| struct RsaPkcs1Signer<D> { | |
| key: rsa::PrivateKey, | |
| _p: PhantomData<fn() -> D>, | |
| } | |
| impl<D> Debug for RsaPkcs1Signer<D> { | |
| fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { | |
| f.debug_struct("RsaPkcs1Signer").finish() | |
| } | |
| } | |
| impl<D: RsaSignatureDigest> RsaPkcs1Signer<D> { | |
| fn new(key: rsa::PrivateKey) -> Self { | |
| Self { | |
| key, | |
| _p: PhantomData, | |
| } | |
| } | |
| } | |
| impl<D: RsaSignatureDigest> Signer for RsaPkcs1Signer<D> { | |
| fn sign(&self, message: &[u8]) -> Result<Vec<u8>, Error> { | |
| Ok(self.key.sign_pkcs1::<D>(message)) | |
| } | |
| fn scheme(&self) -> SignatureScheme { | |
| match D::ALGORITHM { | |
| pki::DigestAlgorithm::Sha256 => SignatureScheme::RSA_PKCS1_SHA256, | |
| pki::DigestAlgorithm::Sha384 => SignatureScheme::RSA_PKCS1_SHA384, | |
| pki::DigestAlgorithm::Sha512 => SignatureScheme::RSA_PKCS1_SHA512, | |
| } | |
| } | |
| } | |
| struct RsaPssSigner<D> { | |
| key: rsa::PrivateKey, | |
| _p: PhantomData<fn() -> D>, | |
| } | |
| impl<D> Debug for RsaPssSigner<D> { | |
| fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { | |
| f.debug_struct("RsaPssSigner").finish() | |
| } | |
| } | |
| impl<D: RsaSignatureDigest> RsaPssSigner<D> { | |
| fn new(key: rsa::PrivateKey) -> Self { | |
| Self { | |
| key, | |
| _p: PhantomData, | |
| } | |
| } | |
| } | |
| impl<D: RsaSignatureDigest> Signer for RsaPssSigner<D> { | |
| fn sign(&self, message: &[u8]) -> Result<Vec<u8>, Error> { | |
| Ok(self.key.sign_pss::<D>(message)) | |
| } | |
| fn scheme(&self) -> SignatureScheme { | |
| match D::ALGORITHM { | |
| pki::DigestAlgorithm::Sha256 => SignatureScheme::RSA_PSS_SHA256, | |
| pki::DigestAlgorithm::Sha384 => SignatureScheme::RSA_PSS_SHA384, | |
| pki::DigestAlgorithm::Sha512 => SignatureScheme::RSA_PSS_SHA512, | |
| } | |
| } | |
| } | |
| impl SigningKey for RsaPrivateKey { | |
| fn choose_scheme(&self, offered: &[SignatureScheme]) -> Option<Box<dyn Signer>> { | |
| for offer in offered { | |
| match offer { | |
| SignatureScheme::RSA_PKCS1_SHA1 => continue, | |
| SignatureScheme::RSA_PKCS1_SHA256 => { | |
| return Some(Box::new(RsaPkcs1Signer::<digest::Sha256>::new( | |
| self.0.clone(), | |
| ))); | |
| } | |
| SignatureScheme::RSA_PKCS1_SHA384 => { | |
| return Some(Box::new(RsaPkcs1Signer::<digest::Sha384>::new( | |
| self.0.clone(), | |
| ))); | |
| } | |
| SignatureScheme::RSA_PKCS1_SHA512 => { | |
| return Some(Box::new(RsaPkcs1Signer::<digest::Sha512>::new( | |
| self.0.clone(), | |
| ))); | |
| } | |
| SignatureScheme::RSA_PSS_SHA256 => { | |
| return Some(Box::new(RsaPssSigner::<digest::Sha256>::new( | |
| self.0.clone(), | |
| ))); | |
| } | |
| SignatureScheme::RSA_PSS_SHA384 => { | |
| return Some(Box::new(RsaPssSigner::<digest::Sha384>::new( | |
| self.0.clone(), | |
| ))); | |
| } | |
| SignatureScheme::RSA_PSS_SHA512 => { | |
| return Some(Box::new(RsaPssSigner::<digest::Sha512>::new( | |
| self.0.clone(), | |
| ))); | |
| } | |
| _ => continue, | |
| } | |
| } | |
| None | |
| } | |
| fn algorithm(&self) -> SignatureAlgorithm { | |
| SignatureAlgorithm::RSA | |
| } | |
| } | |
| /// An ECDSA signing key | |
| #[derive(Clone)] | |
| pub(crate) struct EcdsaPrivateKey<C: ec::Curve>(pub ecdsa::PrivateKey<C>); | |
| impl<C: ec::Curve> Debug for EcdsaPrivateKey<C> { | |
| fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { | |
| f.debug_tuple("EcdsaPrivateKey").finish() | |
| } | |
| } | |
| impl<C: ec::Curve> TryFrom<&'_ PrivateSec1KeyDer<'_>> for EcdsaPrivateKey<C> { | |
| type Error = Error; | |
| fn try_from(der: &PrivateSec1KeyDer) -> Result<Self, Self::Error> { | |
| let der = der.secret_sec1_der(); | |
| let key = ecdsa::PrivateKey::from_der_ec_private_key(der) | |
| .ok_or(Error::General("Cannot parse Sec1 key from DER".into()))?; | |
| Ok(Self(key)) | |
| } | |
| } | |
| macro_rules! ecdsa_signer { | |
| ($scheme:path, $curve:path) => { | |
| impl SigningKey for EcdsaPrivateKey<$curve> { | |
| fn choose_scheme(&self, offered: &[SignatureScheme]) -> Option<Box<dyn Signer>> { | |
| for offer in offered { | |
| match offer { | |
| // We do not support any SHA1 scheme | |
| SignatureScheme::ECDSA_SHA1_Legacy => continue, | |
| $scheme => return Some(Box::new(EcdsaSigner(self.0.clone()))), | |
| _ => continue, | |
| } | |
| } | |
| None | |
| } | |
| fn algorithm(&self) -> SignatureAlgorithm { | |
| SignatureAlgorithm::ECDSA | |
| } | |
| } | |
| impl Signer for EcdsaSigner<$curve> { | |
| fn sign(&self, message: &[u8]) -> Result<Vec<u8>, Error> { | |
| Ok(self.0.sign(message)) | |
| } | |
| fn scheme(&self) -> SignatureScheme { | |
| $scheme | |
| } | |
| } | |
| }; | |
| } | |
| ecdsa_signer!(SignatureScheme::ECDSA_NISTP256_SHA256, ec::P256); | |
| ecdsa_signer!(SignatureScheme::ECDSA_NISTP384_SHA384, ec::P384); | |
| struct EcdsaSigner<C: ec::Curve>(ecdsa::PrivateKey<C>); | |
| impl<C: ec::Curve> Debug for EcdsaSigner<C> { | |
| fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { | |
| f.debug_tuple("EcdsaSigner").finish() | |
| } | |
| } | |
| #[derive(Clone)] | |
| pub(crate) struct EddsaPrivateKey(pub ed25519::PrivateKey); | |
| impl Debug for EddsaPrivateKey { | |
| fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { | |
| f.debug_tuple("EddsaPrivateKey").finish() | |
| } | |
| } | |
| impl SigningKey for EddsaPrivateKey { | |
| fn choose_scheme(&self, offered: &[SignatureScheme]) -> Option<Box<dyn Signer>> { | |
| for offer in offered { | |
| if matches!(offer, SignatureScheme::ED25519) { | |
| return Some(Box::new(EddsaSigner(self.0.clone()))); | |
| } | |
| } | |
| None | |
| } | |
| fn algorithm(&self) -> SignatureAlgorithm { | |
| SignatureAlgorithm::ED25519 | |
| } | |
| } | |
| struct EddsaSigner(ed25519::PrivateKey); | |
| impl Debug for EddsaSigner { | |
| fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { | |
| f.debug_tuple("EddsaSigner").finish() | |
| } | |
| } | |
| impl Signer for EddsaSigner { | |
| fn sign(&self, message: &[u8]) -> Result<Vec<u8>, Error> { | |
| Ok(self.0.sign(message).to_vec()) | |
| } | |
| fn scheme(&self) -> SignatureScheme { | |
| SignatureScheme::ED25519 | |
| } | |
| } |