lib.rs
  1  use std::mem::MaybeUninit;
  2  
  3  #[allow(
  4      non_camel_case_types,
  5      unsafe_op_in_unsafe_fn,
  6      clippy::missing_safety_doc
  7  )]
  8  pub mod bindings;
  9  
 10  pub type XSalsa20Key = [u8; 32];
 11  pub type XSalsa20Nonce = [u8; 24];
 12  
 13  pub type Poly1305Key = bindings::poly1305_key;
 14  pub type Poly1305Tag = bindings::poly1305_mac;
 15  
 16  #[repr(transparent)]
 17  pub struct XSalsa20(bindings::crypton_salsa_context);
 18  
 19  impl XSalsa20 {
 20      pub const KEY_LEN: usize = std::mem::size_of::<XSalsa20Key>();
 21      pub const NONCE_LEN: usize = std::mem::size_of::<XSalsa20Nonce>();
 22  
 23      pub fn init(key: &XSalsa20Key, nonce: &XSalsa20Nonce) -> Self {
 24          let mut xsalsa20: MaybeUninit<bindings::crypton_salsa_context> = MaybeUninit::uninit();
 25  
 26          let xsalsa20 = unsafe {
 27              let ctx: *mut bindings::crypton_salsa_context = xsalsa20.as_mut_ptr();
 28              let nb_rounds: u8 = 20;
 29              let keylen: u32 = Self::KEY_LEN as u32;
 30              let key: *const u8 = key.as_ptr();
 31              let ivlen = Self::NONCE_LEN as u32;
 32              let iv: *const u8 = nonce.as_ptr();
 33  
 34              bindings::crypton_xsalsa_init(ctx, nb_rounds, keylen, key, ivlen, iv);
 35              xsalsa20.assume_init()
 36          };
 37  
 38          Self(xsalsa20)
 39      }
 40  
 41      pub fn derive(mut self, iv: &[u8; 16]) -> Self {
 42          unsafe {
 43              let ctx: *mut bindings::crypton_salsa_context = self.as_mut_ptr();
 44              let ivlen: u32 = std::mem::size_of_val(iv) as u32;
 45              let iv: *const u8 = iv.as_ptr();
 46  
 47              bindings::crypton_xsalsa_derive(ctx, ivlen, iv);
 48              self
 49          }
 50      }
 51  
 52      pub fn generate_into(&mut self, output: &mut [u8]) {
 53          unsafe {
 54              let dst: *mut u8 = output.as_mut_ptr();
 55              let st: *mut bindings::crypton_salsa_context = self.as_mut_ptr();
 56              let bytes = output.len().try_into().unwrap();
 57  
 58              bindings::crypton_salsa_generate(dst, st, bytes);
 59          }
 60      }
 61  
 62      pub fn generate(&mut self, bytes: usize) -> Vec<u8> {
 63          let mut output = vec![0u8; bytes];
 64          self.generate_into(&mut output);
 65          output
 66      }
 67  
 68      pub fn combine_into(&mut self, src: &[u8], output: &mut [u8]) {
 69          assert!(
 70              src.len() <= output.len(),
 71              "combine_into: src.len > output.len"
 72          );
 73  
 74          unsafe {
 75              let dst: *mut u8 = output.as_mut_ptr();
 76              let st: *mut bindings::crypton_salsa_context = self.as_mut_ptr();
 77              let src: *const u8 = src.as_ptr();
 78              let bytes: u32 = output.len().try_into().unwrap();
 79  
 80              bindings::crypton_salsa_combine(dst, st, src, bytes);
 81          }
 82      }
 83  
 84      pub fn combine(&mut self, src: &[u8]) -> Vec<u8> {
 85          let mut output = vec![0u8; src.len()];
 86          self.combine_into(src, &mut output);
 87          output
 88      }
 89  
 90      pub fn as_ptr(&self) -> *const bindings::crypton_salsa_context {
 91          // repr: transparent
 92          self as *const Self as *const bindings::crypton_salsa_context
 93      }
 94  
 95      pub fn as_mut_ptr(&mut self) -> *mut bindings::crypton_salsa_context {
 96          // repr: transparent
 97          self as *mut Self as *mut bindings::crypton_salsa_context
 98      }
 99  }
100  
101  #[repr(transparent)]
102  pub struct Poly1305(bindings::poly1305_ctx);
103  
104  impl Poly1305 {
105      pub const KEY_LEN: usize = std::mem::size_of::<Poly1305Key>();
106      pub const TAG_LEN: usize = std::mem::size_of::<Poly1305Tag>();
107  
108      pub fn init(key: &mut Poly1305Key) -> Self {
109          let mut poly1305: MaybeUninit<bindings::poly1305_ctx> = MaybeUninit::uninit();
110  
111          let poly1305 = unsafe {
112              let ctx: *mut bindings::poly1305_ctx = poly1305.as_mut_ptr();
113              let key: *mut bindings::poly1305_key = key as *mut bindings::poly1305_key;
114  
115              bindings::crypton_poly1305_init(ctx, key);
116              poly1305.assume_init()
117          };
118  
119          Self(poly1305)
120      }
121  
122      pub fn update(&mut self, input: &mut [u8]) {
123          unsafe {
124              let ctx: *mut bindings::poly1305_ctx = self.as_mut_ptr();
125              let data: *mut u8 = input.as_mut_ptr();
126              let length: u32 = input.len().try_into().unwrap();
127  
128              bindings::crypton_poly1305_update(ctx, data, length);
129          }
130      }
131  
132      pub fn finalize(&mut self) -> Poly1305Tag {
133          let mut tag: Poly1305Tag = [0u8; 16];
134  
135          unsafe {
136              let ctx: *mut bindings::poly1305_ctx = self.as_mut_ptr();
137              let mac: *mut u8 = tag.as_mut_ptr();
138  
139              bindings::crypton_poly1305_finalize(mac, ctx);
140          }
141  
142          tag
143      }
144  
145      pub fn as_ptr(&self) -> *const bindings::poly1305_ctx {
146          // repr: transparent
147          self as *const Self as *mut bindings::poly1305_ctx
148      }
149  
150      pub fn as_mut_ptr(&mut self) -> *mut bindings::poly1305_ctx {
151          // repr: transparent
152          self as *mut Self as *mut bindings::poly1305_ctx
153      }
154  }