botan/
pk_ops.rs

1use crate::utils::*;
2use botan_sys::*;
3
4use crate::pubkey::{Privkey, Pubkey};
5use crate::rng::RandomNumberGenerator;
6
7#[derive(Debug)]
8/// An object that can generate signatures
9///
10/// # Examples
11///
12/// ```
13/// let mut rng = botan::RandomNumberGenerator::new_system().unwrap();
14/// let rsa = botan::Privkey::create("RSA", "2048", &mut rng).unwrap();
15/// let mut signer = botan::Signer::new(&rsa, "PKCS1v15(SHA-256)").unwrap();
16/// signer.update(&[1,2,3]).unwrap();
17/// let signature = signer.finish(&mut rng).unwrap();
18/// ```
19pub struct Signer {
20    obj: botan_pk_op_sign_t,
21    sig_len: usize,
22}
23
24unsafe impl Sync for Signer {}
25unsafe impl Send for Signer {}
26
27botan_impl_drop!(Signer, botan_pk_op_sign_destroy);
28
29impl Signer {
30    /// Create a new signature operator
31    pub fn new(key: &Privkey, padding: &str) -> Result<Signer> {
32        let padding = make_cstr(padding)?;
33        let obj = botan_init!(
34            botan_pk_op_sign_create,
35            key.handle(),
36            padding.as_ptr(),
37            0u32
38        )?;
39        let sig_len = botan_usize!(botan_pk_op_sign_output_length, obj)?;
40        Ok(Signer { obj, sig_len })
41    }
42
43    /// Create a new signature operator that outputs DER-formatted signatures
44    pub fn new_with_der_formatted_signatures(key: &Privkey, padding: &str) -> Result<Signer> {
45        let padding = make_cstr(padding)?;
46        let obj = botan_init!(
47            botan_pk_op_sign_create,
48            key.handle(),
49            padding.as_ptr(),
50            1u32
51        )?;
52        let sig_len = botan_usize!(botan_pk_op_sign_output_length, obj)?;
53        Ok(Signer { obj, sig_len })
54    }
55
56    /// Add more bytes of the message that will be signed
57    pub fn update(&mut self, data: &[u8]) -> Result<()> {
58        botan_call!(botan_pk_op_sign_update, self.obj, data.as_ptr(), data.len())
59    }
60
61    /// Complete and return the signature
62    pub fn finish(&mut self, rng: &mut RandomNumberGenerator) -> Result<Vec<u8>> {
63        let rng_handle = rng.handle();
64        call_botan_ffi_returning_vec_u8(self.sig_len, &|out_buf, out_len| unsafe {
65            botan_pk_op_sign_finish(self.obj, rng_handle, out_buf, out_len)
66        })
67    }
68}
69
70#[derive(Debug)]
71/// An object that can perform public key decryption
72pub struct Decryptor {
73    obj: botan_pk_op_decrypt_t,
74}
75
76unsafe impl Sync for Decryptor {}
77unsafe impl Send for Decryptor {}
78
79botan_impl_drop!(Decryptor, botan_pk_op_decrypt_destroy);
80
81impl Decryptor {
82    /// Create a new decryption object
83    pub fn new(key: &Privkey, padding: &str) -> Result<Decryptor> {
84        let padding = make_cstr(padding)?;
85        let obj = botan_init!(
86            botan_pk_op_decrypt_create,
87            key.handle(),
88            padding.as_ptr(),
89            0u32
90        )?;
91        Ok(Decryptor { obj })
92    }
93
94    /// Decrypt a message
95    pub fn decrypt(&mut self, ctext: &[u8]) -> Result<Vec<u8>> {
96        let mut ptext_len = 0;
97
98        botan_call!(
99            botan_pk_op_decrypt_output_length,
100            self.obj,
101            ctext.len(),
102            &mut ptext_len
103        )?;
104
105        call_botan_ffi_returning_vec_u8(ptext_len, &|out_buf, out_len| unsafe {
106            botan_pk_op_decrypt(self.obj, out_buf, out_len, ctext.as_ptr(), ctext.len())
107        })
108    }
109}
110
111#[derive(Debug)]
112/// An object that can perform public key signature verification
113pub struct Verifier {
114    obj: botan_pk_op_verify_t,
115}
116
117unsafe impl Sync for Verifier {}
118unsafe impl Send for Verifier {}
119
120botan_impl_drop!(Verifier, botan_pk_op_verify_destroy);
121
122impl Verifier {
123    /// Create a new verifier object
124    pub fn new(key: &Pubkey, padding: &str) -> Result<Verifier> {
125        let padding = make_cstr(padding)?;
126        let obj = botan_init!(
127            botan_pk_op_verify_create,
128            key.handle(),
129            padding.as_ptr(),
130            0u32
131        )?;
132        Ok(Verifier { obj })
133    }
134
135    /// Create a new verifier object
136    pub fn new_with_der_formatted_signatures(key: &Pubkey, padding: &str) -> Result<Verifier> {
137        let padding = make_cstr(padding)?;
138        let obj = botan_init!(
139            botan_pk_op_verify_create,
140            key.handle(),
141            padding.as_ptr(),
142            1u32
143        )?;
144        Ok(Verifier { obj })
145    }
146
147    /// Add more bytes of the message that will be verified
148    pub fn update(&mut self, data: &[u8]) -> Result<()> {
149        botan_call!(
150            botan_pk_op_verify_update,
151            self.obj,
152            data.as_ptr(),
153            data.len()
154        )
155    }
156
157    /// Verify the provided signature and return true if valid
158    pub fn finish(&mut self, signature: &[u8]) -> Result<bool> {
159        match unsafe { botan_pk_op_verify_finish(self.obj, signature.as_ptr(), signature.len()) } {
160            0 => Ok(true),
161            BOTAN_FFI_INVALID_VERIFIER => Ok(false),
162            e => Err(Error::from_rc(e)),
163        }
164    }
165}
166
167#[derive(Debug)]
168/// An object that performs public key encryption
169///
170/// # Examples
171///
172/// ```
173/// let mut rng = botan::RandomNumberGenerator::new_system().unwrap();
174/// let rsa = botan::Privkey::create("RSA", "2048", &mut rng).unwrap();
175/// let rsa_pub = rsa.pubkey().unwrap();
176/// let mut enc = botan::Encryptor::new(&rsa_pub, "OAEP(SHA-256)").unwrap();
177/// let ctext = enc.encrypt(&[1,2,3], &mut rng).unwrap();
178/// ```
179pub struct Encryptor {
180    obj: botan_pk_op_encrypt_t,
181}
182
183unsafe impl Sync for Encryptor {}
184unsafe impl Send for Encryptor {}
185
186botan_impl_drop!(Encryptor, botan_pk_op_encrypt_destroy);
187
188impl Encryptor {
189    /// Create a new public key encryptor object
190    pub fn new(key: &Pubkey, padding: &str) -> Result<Encryptor> {
191        let padding = make_cstr(padding)?;
192        let obj = botan_init!(
193            botan_pk_op_encrypt_create,
194            key.handle(),
195            padding.as_ptr(),
196            0u32
197        )?;
198        Ok(Encryptor { obj })
199    }
200
201    /// Encrypt a message using the provided public key
202    pub fn encrypt(&mut self, ptext: &[u8], rng: &mut RandomNumberGenerator) -> Result<Vec<u8>> {
203        let mut ctext_len = 0;
204        botan_call!(
205            botan_pk_op_encrypt_output_length,
206            self.obj,
207            ptext.len(),
208            &mut ctext_len
209        )?;
210
211        let rng_handle = rng.handle();
212
213        call_botan_ffi_returning_vec_u8(ctext_len, &|out_buf, out_len| unsafe {
214            botan_pk_op_encrypt(
215                self.obj,
216                rng_handle,
217                out_buf,
218                out_len,
219                ptext.as_ptr(),
220                ptext.len(),
221            )
222        })
223    }
224}
225
226#[derive(Debug)]
227/// An object that performs key agreement
228pub struct KeyAgreement {
229    obj: botan_pk_op_ka_t,
230}
231
232unsafe impl Sync for KeyAgreement {}
233unsafe impl Send for KeyAgreement {}
234
235botan_impl_drop!(KeyAgreement, botan_pk_op_key_agreement_destroy);
236
237impl KeyAgreement {
238    /// Create a new key agreement operator
239    pub fn new(key: &Privkey, kdf: &str) -> Result<KeyAgreement> {
240        let kdf = make_cstr(kdf)?;
241        let obj = botan_init!(
242            botan_pk_op_key_agreement_create,
243            key.handle(),
244            kdf.as_ptr(),
245            0u32
246        )?;
247        Ok(KeyAgreement { obj })
248    }
249
250    /// Perform key agreement operation
251    pub fn agree(
252        &mut self,
253        requested_output: usize,
254        counterparty_key: &[u8],
255        salt: &[u8],
256    ) -> Result<Vec<u8>> {
257        let mut ka_len = requested_output;
258
259        if ka_len == 0 {
260            ka_len = botan_usize!(botan_pk_op_key_agreement_size, self.obj)?;
261        }
262
263        call_botan_ffi_returning_vec_u8(ka_len, &|out_buf, out_len| unsafe {
264            botan_pk_op_key_agreement(
265                self.obj,
266                out_buf,
267                out_len,
268                counterparty_key.as_ptr(),
269                counterparty_key.len(),
270                salt.as_ptr(),
271                salt.len(),
272            )
273        })
274    }
275}