@@ -35,6 +35,7 @@ mod aead_params {
3535 frozen,
3636 eq,
3737 hash,
38+ from_py_object,
3839 module = "cryptography.hazmat.bindings._rust.openssl.hpke"
3940) ]
4041#[ derive( Clone , PartialEq , Eq , Hash ) ]
@@ -48,6 +49,7 @@ pub(crate) enum KEM {
4849 frozen,
4950 eq,
5051 hash,
52+ from_py_object,
5153 module = "cryptography.hazmat.bindings._rust.openssl.hpke"
5254) ]
5355#[ derive( Clone , PartialEq , Eq , Hash ) ]
@@ -61,6 +63,7 @@ pub(crate) enum KDF {
6163 frozen,
6264 eq,
6365 hash,
66+ from_py_object,
6467 module = "cryptography.hazmat.bindings._rust.openssl.hpke"
6568) ]
6669#[ derive( Clone , PartialEq , Eq , Hash ) ]
@@ -231,6 +234,64 @@ impl Suite {
231234 self . hkdf_expand ( py, prk, & labeled_info, length)
232235 }
233236
237+ fn encrypt_inner < ' p > (
238+ & self ,
239+ py : pyo3:: Python < ' p > ,
240+ plaintext : CffiBuf < ' _ > ,
241+ public_key : & pyo3:: Bound < ' _ , pyo3:: PyAny > ,
242+ info : Option < CffiBuf < ' _ > > ,
243+ aad : Option < CffiBuf < ' _ > > ,
244+ ) -> CryptographyResult < pyo3:: Bound < ' p , pyo3:: types:: PyBytes > > {
245+ let info_bytes: & [ u8 ] = info. as_ref ( ) . map ( |b| b. as_bytes ( ) ) . unwrap_or ( b"" ) ;
246+
247+ let ( shared_secret, enc) = self . encap ( py, public_key) ?;
248+ let ( key, base_nonce) = self . key_schedule ( py, shared_secret. as_bytes ( ) , info_bytes) ?;
249+
250+ let aesgcm = AesGcm :: new ( py, pyo3:: types:: PyBytes :: new ( py, & key) . unbind ( ) . into_any ( ) ) ?;
251+ let ct = aesgcm. encrypt ( py, CffiBuf :: from_bytes ( py, & base_nonce) , plaintext, aad) ?;
252+
253+ let enc_bytes = enc. as_bytes ( ) ;
254+ let ct_bytes = ct. as_bytes ( ) ;
255+ Ok ( pyo3:: types:: PyBytes :: new_with (
256+ py,
257+ enc_bytes. len ( ) + ct_bytes. len ( ) ,
258+ |buf| {
259+ buf[ ..enc_bytes. len ( ) ] . copy_from_slice ( enc_bytes) ;
260+ buf[ enc_bytes. len ( ) ..] . copy_from_slice ( ct_bytes) ;
261+ Ok ( ( ) )
262+ } ,
263+ ) ?)
264+ }
265+
266+ fn decrypt_inner < ' p > (
267+ & self ,
268+ py : pyo3:: Python < ' p > ,
269+ ciphertext : CffiBuf < ' _ > ,
270+ private_key : & pyo3:: Bound < ' _ , pyo3:: PyAny > ,
271+ info : Option < CffiBuf < ' _ > > ,
272+ aad : Option < CffiBuf < ' _ > > ,
273+ ) -> CryptographyResult < pyo3:: Bound < ' p , pyo3:: types:: PyBytes > > {
274+ let ct_bytes = ciphertext. as_bytes ( ) ;
275+ if ct_bytes. len ( ) < kem_params:: X25519_NENC {
276+ return Err ( CryptographyError :: from ( exceptions:: InvalidTag :: new_err ( ( ) ) ) ) ;
277+ }
278+
279+ let info_bytes: & [ u8 ] = info. as_ref ( ) . map ( |b| b. as_bytes ( ) ) . unwrap_or ( b"" ) ;
280+
281+ let ( enc, ct) = ct_bytes. split_at ( kem_params:: X25519_NENC ) ;
282+
283+ let shared_secret = self . decap ( py, enc, private_key) ?;
284+ let ( key, base_nonce) = self . key_schedule ( py, shared_secret. as_bytes ( ) , info_bytes) ?;
285+
286+ let aesgcm = AesGcm :: new ( py, pyo3:: types:: PyBytes :: new ( py, & key) . unbind ( ) . into_any ( ) ) ?;
287+ aesgcm. decrypt (
288+ py,
289+ CffiBuf :: from_bytes ( py, & base_nonce) ,
290+ CffiBuf :: from_bytes ( py, ct) ,
291+ aad,
292+ )
293+ }
294+
234295 fn key_schedule (
235296 & self ,
236297 py : pyo3:: Python < ' _ > ,
@@ -293,69 +354,57 @@ impl Suite {
293354 } )
294355 }
295356
296- #[ pyo3( signature = ( plaintext, public_key, info=None , aad= None ) ) ]
357+ #[ pyo3( signature = ( plaintext, public_key, info=None ) ) ]
297358 fn encrypt < ' p > (
298359 & self ,
299360 py : pyo3:: Python < ' p > ,
300361 plaintext : CffiBuf < ' _ > ,
301362 public_key : & pyo3:: Bound < ' _ , pyo3:: PyAny > ,
302363 info : Option < CffiBuf < ' _ > > ,
303- aad : Option < CffiBuf < ' _ > > ,
304364 ) -> CryptographyResult < pyo3:: Bound < ' p , pyo3:: types:: PyBytes > > {
305- let info_bytes: & [ u8 ] = info. as_ref ( ) . map ( |b| b. as_bytes ( ) ) . unwrap_or ( b"" ) ;
306-
307- let ( shared_secret, enc) = self . encap ( py, public_key) ?;
308- let ( key, base_nonce) = self . key_schedule ( py, shared_secret. as_bytes ( ) , info_bytes) ?;
309-
310- let aesgcm = AesGcm :: new ( py, pyo3:: types:: PyBytes :: new ( py, & key) . unbind ( ) . into_any ( ) ) ?;
311- let ct = aesgcm. encrypt ( py, CffiBuf :: from_bytes ( py, & base_nonce) , plaintext, aad) ?;
312-
313- let enc_bytes = enc. as_bytes ( ) ;
314- let ct_bytes = ct. as_bytes ( ) ;
315- Ok ( pyo3:: types:: PyBytes :: new_with (
316- py,
317- enc_bytes. len ( ) + ct_bytes. len ( ) ,
318- |buf| {
319- buf[ ..enc_bytes. len ( ) ] . copy_from_slice ( enc_bytes) ;
320- buf[ enc_bytes. len ( ) ..] . copy_from_slice ( ct_bytes) ;
321- Ok ( ( ) )
322- } ,
323- ) ?)
365+ self . encrypt_inner ( py, plaintext, public_key, info, None )
324366 }
325367
326- #[ pyo3( signature = ( ciphertext, private_key, info=None , aad= None ) ) ]
368+ #[ pyo3( signature = ( ciphertext, private_key, info=None ) ) ]
327369 fn decrypt < ' p > (
328370 & self ,
329371 py : pyo3:: Python < ' p > ,
330372 ciphertext : CffiBuf < ' _ > ,
331373 private_key : & pyo3:: Bound < ' _ , pyo3:: PyAny > ,
332374 info : Option < CffiBuf < ' _ > > ,
333- aad : Option < CffiBuf < ' _ > > ,
334375 ) -> CryptographyResult < pyo3:: Bound < ' p , pyo3:: types:: PyBytes > > {
335- let ct_bytes = ciphertext. as_bytes ( ) ;
336- if ct_bytes. len ( ) < kem_params:: X25519_NENC {
337- return Err ( CryptographyError :: from ( exceptions:: InvalidTag :: new_err ( ( ) ) ) ) ;
338- }
339-
340- let info_bytes: & [ u8 ] = info. as_ref ( ) . map ( |b| b. as_bytes ( ) ) . unwrap_or ( b"" ) ;
341-
342- let ( enc, ct) = ct_bytes. split_at ( kem_params:: X25519_NENC ) ;
376+ self . decrypt_inner ( py, ciphertext, private_key, info, None )
377+ }
378+ }
343379
344- let shared_secret = self . decap ( py, enc, private_key) ?;
345- let ( key, base_nonce) = self . key_schedule ( py, shared_secret. as_bytes ( ) , info_bytes) ?;
380+ #[ pyo3:: pyfunction]
381+ #[ pyo3( signature = ( suite, plaintext, public_key, info=None , aad=None ) ) ]
382+ fn _encrypt_with_aad < ' p > (
383+ py : pyo3:: Python < ' p > ,
384+ suite : & Suite ,
385+ plaintext : CffiBuf < ' _ > ,
386+ public_key : & pyo3:: Bound < ' _ , pyo3:: PyAny > ,
387+ info : Option < CffiBuf < ' _ > > ,
388+ aad : Option < CffiBuf < ' _ > > ,
389+ ) -> CryptographyResult < pyo3:: Bound < ' p , pyo3:: types:: PyBytes > > {
390+ suite. encrypt_inner ( py, plaintext, public_key, info, aad)
391+ }
346392
347- let aesgcm = AesGcm :: new ( py, pyo3:: types:: PyBytes :: new ( py, & key) . unbind ( ) . into_any ( ) ) ?;
348- aesgcm. decrypt (
349- py,
350- CffiBuf :: from_bytes ( py, & base_nonce) ,
351- CffiBuf :: from_bytes ( py, ct) ,
352- aad,
353- )
354- }
393+ #[ pyo3:: pyfunction]
394+ #[ pyo3( signature = ( suite, ciphertext, private_key, info=None , aad=None ) ) ]
395+ fn _decrypt_with_aad < ' p > (
396+ py : pyo3:: Python < ' p > ,
397+ suite : & Suite ,
398+ ciphertext : CffiBuf < ' _ > ,
399+ private_key : & pyo3:: Bound < ' _ , pyo3:: PyAny > ,
400+ info : Option < CffiBuf < ' _ > > ,
401+ aad : Option < CffiBuf < ' _ > > ,
402+ ) -> CryptographyResult < pyo3:: Bound < ' p , pyo3:: types:: PyBytes > > {
403+ suite. decrypt_inner ( py, ciphertext, private_key, info, aad)
355404}
356405
357406#[ pyo3:: pymodule( gil_used = false ) ]
358407pub ( crate ) mod hpke {
359408 #[ pymodule_export]
360- use super :: { Suite , AEAD , KDF , KEM } ;
409+ use super :: { Suite , _decrypt_with_aad , _encrypt_with_aad , AEAD , KDF , KEM } ;
361410}
0 commit comments