crypto_api_chachapoly/
chacha20_ietf.rs1use crate::core::chacha20::chacha20_ietf_block;
2use crypto_api::{
3 cipher::{ CipherInfo, Cipher },
4 rng::{ SecureRng, SecKeyGen }
5};
6use std::{ cmp::min, error::Error };
7
8
9#[cfg(target_pointer_width = "64")]
11pub const CHACHA20_MAX: usize = 4_294_967_296 * 64; #[cfg(target_pointer_width = "32")]
14pub const CHACHA20_MAX: usize = usize::max_value(); pub const CHACHA20_KEY: usize = 32;
19pub const CHACHA20_NONCE: usize = 12;
21
22
23pub struct ChaCha20Ietf;
25impl ChaCha20Ietf {
26 pub fn cipher() -> Box<dyn Cipher> {
28 Box::new(Self)
29 }
30
31 pub fn xor(key: &[u8], nonce: &[u8], mut n: u32, mut data: &mut[u8]) {
42 assert_eq!(CHACHA20_KEY, key.len());
44 assert_eq!(CHACHA20_NONCE, nonce.len());
45
46 let mut buf = vec![0; 64];
48 while !data.is_empty() {
49 chacha20_ietf_block(key, nonce, n, &mut buf);
51 n = n.checked_add(1).expect("The ChaCha20-IETF block counter must not exceed 2^32 - 1");
52
53 let to_xor = min(data.len(), buf.len());
55 (0..to_xor).for_each(|i| data[i] = xor!(data[i], buf[i]));
56 data = &mut data[to_xor..];
57 }
58 }
59}
60impl SecKeyGen for ChaCha20Ietf {
61 fn new_sec_key(&self, buf: &mut[u8], rng: &mut dyn SecureRng) -> Result<usize, Box<dyn Error + 'static>> {
62 vfy_keygen!(CHACHA20_KEY => buf);
64
65 rng.random(&mut buf[..CHACHA20_KEY])?;
67 Ok(CHACHA20_KEY)
68 }
69}
70impl Cipher for ChaCha20Ietf {
71 fn info(&self) -> CipherInfo {
72 CipherInfo {
73 name: "ChaCha20Ietf", is_otc: true,
74 key_len_r: CHACHA20_KEY..(CHACHA20_KEY + 1),
75 nonce_len_r: CHACHA20_NONCE..(CHACHA20_NONCE + 1),
76 aead_tag_len_r: 0..(0 + 1)
77 }
78 }
79
80 fn encrypted_len_max(&self, plaintext_len: usize) -> usize {
81 plaintext_len
82 }
83
84 fn encrypt(&self, buf: &mut[u8], plaintext_len: usize, key: &[u8], nonce: &[u8])
85 -> Result<usize, Box<dyn Error + 'static>>
86 {
87 vfy_enc!(
89 key => [CHACHA20_KEY], nonce => [CHACHA20_NONCE],
90 plaintext_len => [buf, CHACHA20_MAX]
91 );
92
93 Self::xor(key, nonce, 0, &mut buf[..plaintext_len]);
95 Ok(plaintext_len)
96 }
97 fn encrypt_to(&self, buf: &mut[u8], plaintext: &[u8], key: &[u8], nonce: &[u8])
98 -> Result<usize, Box<dyn Error + 'static>>
99 {
100 vfy_enc!(
102 key => [CHACHA20_KEY], nonce => [CHACHA20_NONCE],
103 plaintext => [buf, CHACHA20_MAX]
104 );
105
106 buf[..plaintext.len()].copy_from_slice(plaintext);
108 Self::xor(key, nonce, 0, &mut buf[..plaintext.len()]);
109 Ok(plaintext.len())
110 }
111
112 fn decrypt(&self, buf: &mut[u8], ciphertext_len: usize, key: &[u8], nonce: &[u8])
113 -> Result<usize, Box<dyn Error + 'static>>
114 {
115 vfy_dec!(
117 key => [CHACHA20_KEY], nonce => [CHACHA20_NONCE],
118 ciphertext_len => [buf, CHACHA20_MAX]
119 );
120
121 Self::xor(key, nonce, 0, &mut buf[..ciphertext_len]);
123 Ok(ciphertext_len)
124 }
125 fn decrypt_to(&self, buf: &mut[u8], ciphertext: &[u8], key: &[u8], nonce: &[u8])
126 -> Result<usize, Box<dyn Error + 'static>>
127 {
128 vfy_dec!(
130 key => [CHACHA20_KEY], nonce => [CHACHA20_NONCE],
131 ciphertext => [buf, CHACHA20_MAX]
132 );
133
134 buf[..ciphertext.len()].copy_from_slice(ciphertext);
136 Self::xor(key, nonce, 0, &mut buf[..ciphertext.len()]);
137 Ok(ciphertext.len())
138 }
139}