Skip to main content

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