dtls 0.17.1

A pure Rust implementation of DTLS
Documentation
use super::*;
use crate::crypto::crypto_gcm::*;
use crate::prf::*;

#[derive(Clone)]
pub struct CipherSuiteAes128GcmSha256 {
    gcm: Option<CryptoGcm>,
    rsa: bool,
}

impl CipherSuiteAes128GcmSha256 {
    const PRF_MAC_LEN: usize = 0;
    const PRF_KEY_LEN: usize = 16;
    const PRF_IV_LEN: usize = 4;

    pub fn new(rsa: bool) -> Self {
        CipherSuiteAes128GcmSha256 { gcm: None, rsa }
    }
}

impl CipherSuite for CipherSuiteAes128GcmSha256 {
    fn to_string(&self) -> String {
        if self.rsa {
            "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256".to_owned()
        } else {
            "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256".to_owned()
        }
    }

    fn id(&self) -> CipherSuiteId {
        if self.rsa {
            CipherSuiteId::Tls_Ecdhe_Rsa_With_Aes_128_Gcm_Sha256
        } else {
            CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_128_Gcm_Sha256
        }
    }

    fn certificate_type(&self) -> ClientCertificateType {
        if self.rsa {
            ClientCertificateType::RsaSign
        } else {
            ClientCertificateType::EcdsaSign
        }
    }

    fn hash_func(&self) -> CipherSuiteHash {
        CipherSuiteHash::Sha256
    }

    fn is_psk(&self) -> bool {
        false
    }

    fn is_initialized(&self) -> bool {
        self.gcm.is_some()
    }

    fn init(
        &mut self,
        master_secret: &[u8],
        client_random: &[u8],
        server_random: &[u8],
        is_client: bool,
    ) -> Result<()> {
        let keys = prf_encryption_keys(
            master_secret,
            client_random,
            server_random,
            CipherSuiteAes128GcmSha256::PRF_MAC_LEN,
            CipherSuiteAes128GcmSha256::PRF_KEY_LEN,
            CipherSuiteAes128GcmSha256::PRF_IV_LEN,
            self.hash_func(),
        )?;

        if is_client {
            self.gcm = Some(CryptoGcm::new(
                &keys.client_write_key,
                &keys.client_write_iv,
                &keys.server_write_key,
                &keys.server_write_iv,
            ));
        } else {
            self.gcm = Some(CryptoGcm::new(
                &keys.server_write_key,
                &keys.server_write_iv,
                &keys.client_write_key,
                &keys.client_write_iv,
            ));
        }

        Ok(())
    }

    fn encrypt(&self, pkt_rlh: &RecordLayerHeader, raw: &[u8]) -> Result<Vec<u8>> {
        let cg = self.gcm.as_ref().ok_or(Error::Other(
            "CipherSuite has not been initialized, unable to encrypt".to_owned(),
        ))?;
        cg.encrypt(pkt_rlh, raw)
    }

    fn decrypt(&self, input: &[u8]) -> Result<Vec<u8>> {
        let cg = self.gcm.as_ref().ok_or(Error::Other(
            "CipherSuite has not been initialized, unable to decrypt".to_owned(),
        ))?;
        cg.decrypt(input)
    }
}