use crate::{CtxError, ServerHandshakeCtx, TlsServerCtxConfig};
use ytls_traits::CryptoChaCha20Poly1305Processor;
use ytls_traits::CryptoSha256TranscriptProcessor;
use ytls_traits::CryptoSignerP256Processor;
use ytls_traits::Tls13KeyScheduleHandshakeSha256;
use ytls_traits::CryptoConfig;
use ytls_traits::CryptoRng;
use ytls_traits::TlsLeftOut;
use ytls_record::WrappedStaticRecordBuilder;
use ytls_traits::ServerCertificateVerifyBuilder;
use ytls_traits::WrappedHandshakeBuilder;
impl<Config, Crypto, Rng> ServerCertificateVerifyBuilder for ServerHandshakeCtx<Config, Crypto, Rng>
where
Config: TlsServerCtxConfig,
Crypto: CryptoConfig,
Rng: CryptoRng,
{
#[inline]
fn signature_algorithm(&self) -> [u8; 2] {
[0x04, 0x03]
}
#[inline]
fn sign_cert_verify(&self) -> &[u8] {
match self.signature_cert_verify {
Some(ref s) => &s[..self.signature_cert_verify_len],
None => &[],
}
}
}
impl<Config, Crypto, Rng> ServerHandshakeCtx<Config, Crypto, Rng>
where
Config: TlsServerCtxConfig,
Crypto: CryptoConfig,
Rng: CryptoRng,
{
#[inline]
pub(crate) fn do_server_certificate_verify<
L: TlsLeftOut,
T: CryptoSha256TranscriptProcessor,
>(
&mut self,
left: &mut L,
transcript: &mut T,
) -> Result<(), CtxError> {
let key: [u8; 32] = match self.handshake_server_key {
None => return Err(CtxError::MissingHandshakeKey),
Some(k) => k,
};
let nonce: [u8; 12] = match self.handshake_server_iv {
None => return Err(CtxError::MissingHandshakeIv),
Some(ref mut n) => match n.use_and_incr() {
Some(cur) => cur,
None => return Err(CtxError::ExhaustedIv),
},
};
let ctx_transcript = transcript.sha256_fork();
let ctx_hash_input = ctx_transcript.sha256_finalize();
self.cert_verify_hash = Some(ctx_hash_input);
let h = match self.cert_verify_hash {
Some(h) => h,
None => return Err(CtxError::Bug("Missing certificate verify hash.")),
};
let verify: [u8; 130] = [
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x54, 0x4c, 0x53, 0x20, 0x31, 0x2e, 0x33, 0x2c, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65,
0x72, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x56,
0x65, 0x72, 0x69, 0x66, 0x79, 0x00, h[0], h[1], h[2], h[3], h[4], h[5], h[6], h[7], h[8], h[9], h[10], h[11], h[12], h[13],
h[14], h[15], h[16], h[17], h[18], h[19], h[20], h[21], h[22], h[23], h[24], h[25],
h[26], h[27], h[28], h[29], h[30], h[31],
];
let raw_signing_key = self.config.server_private_key();
let signer = match Crypto::sign_p256_init(raw_signing_key) {
Some(signer) => signer,
None => return Err(CtxError::PrivateKey),
};
let mut c_bytes: [u8; 100] = [0; 100];
let c_bytes_len = match signer.sign_p256(&verify, &mut c_bytes) {
None => return Err(CtxError::Crypto),
Some(out_len) => out_len,
};
self.signature_cert_verify = Some(c_bytes);
self.signature_cert_verify_len = c_bytes_len;
let cipher = Crypto::aead_chaha20poly1305(&key);
let mut server_certificate_verify =
WrappedStaticRecordBuilder::<8192>::server_certificate_verify(self)
.map_err(CtxError::Builder)?;
transcript.sha256_update(server_certificate_verify.as_hashing_context_ref());
let tag = if let Ok([additional_data, encrypt_payload]) =
server_certificate_verify.as_disjoint_mut_for_aead()
{
cipher
.encrypt_in_place(&nonce, &additional_data, encrypt_payload.as_mut())
.map_err(|_| CtxError::Bug("Encrypt failure."))?
} else {
return Err(CtxError::Bug(
"Disjoint for AEAD failed at certificate verify.",
));
};
server_certificate_verify.set_auth_tag(&tag);
left.send_record_out(server_certificate_verify.as_encoded_bytes());
Ok(())
}
}