@@ -9,11 +9,17 @@ use std::ops::Deref;
9
9
use cryptography_x509:: csr:: Attribute ;
10
10
use cryptography_x509:: { common, oid, pkcs7} ;
11
11
use once_cell:: sync:: Lazy ;
12
+ #[ cfg( not( CRYPTOGRAPHY_IS_BORINGSSL ) ) ]
13
+ use openssl:: pkcs7:: Pkcs7 ;
14
+ #[ cfg( not( CRYPTOGRAPHY_IS_BORINGSSL ) ) ]
15
+ use pyo3:: IntoPy ;
12
16
13
17
use crate :: asn1:: encode_der_data;
14
18
use crate :: buf:: CffiBuf ;
15
- use crate :: error:: CryptographyResult ;
16
- use crate :: { types, x509} ;
19
+ use crate :: error:: { CryptographyError , CryptographyResult } ;
20
+ #[ cfg( not( CRYPTOGRAPHY_IS_BORINGSSL ) ) ]
21
+ use crate :: x509:: certificate:: load_der_x509_certificate;
22
+ use crate :: { exceptions, types, x509} ;
17
23
18
24
const PKCS7_CONTENT_TYPE_OID : asn1:: ObjectIdentifier = asn1:: oid!( 1 , 2 , 840 , 113549 , 1 , 9 , 3 ) ;
19
25
const PKCS7_MESSAGE_DIGEST_OID : asn1:: ObjectIdentifier = asn1:: oid!( 1 , 2 , 840 , 113549 , 1 , 9 , 4 ) ;
@@ -290,11 +296,96 @@ fn smime_canonicalize(data: &[u8], text_mode: bool) -> (Cow<'_, [u8]>, Cow<'_, [
290
296
}
291
297
}
292
298
299
+ #[ cfg( not( CRYPTOGRAPHY_IS_BORINGSSL ) ) ]
300
+ fn load_pkcs7_certificates (
301
+ py : pyo3:: Python < ' _ > ,
302
+ pkcs7 : Pkcs7 ,
303
+ ) -> CryptographyResult < & pyo3:: types:: PyList > {
304
+ let nid = pkcs7. type_ ( ) . map ( |t| t. nid ( ) ) ;
305
+ if nid != Some ( openssl:: nid:: Nid :: PKCS7_SIGNED ) {
306
+ let nid_string = nid. map_or ( "empty" . to_string ( ) , |n| n. as_raw ( ) . to_string ( ) ) ;
307
+ return Err ( CryptographyError :: from (
308
+ exceptions:: UnsupportedAlgorithm :: new_err ( (
309
+ format ! ( "Only basic signed structures are currently supported. NID for this data was {}" , nid_string) ,
310
+ exceptions:: Reasons :: UNSUPPORTED_SERIALIZATION ,
311
+ ) ) ,
312
+ ) ) ;
313
+ }
314
+
315
+ let signed_certificates = pkcs7. signed ( ) . and_then ( |x| x. certificates ( ) ) ;
316
+ match signed_certificates {
317
+ None => Err ( CryptographyError :: from (
318
+ pyo3:: exceptions:: PyValueError :: new_err (
319
+ "The provided PKCS7 has no certificate data, but a cert loading method was called." ,
320
+ ) ,
321
+ ) ) ,
322
+ Some ( certificates) => {
323
+ let result = pyo3:: types:: PyList :: empty ( py) ;
324
+ for c in certificates {
325
+ let cert_der = pyo3:: types:: PyBytes :: new ( py, c. to_der ( ) ?. as_slice ( ) ) . into_py ( py) ;
326
+ let cert = load_der_x509_certificate ( py, cert_der, None ) ?;
327
+ result. append ( cert. into_py ( py) ) ?;
328
+ }
329
+ Ok ( result)
330
+ }
331
+ }
332
+ }
333
+
334
+ #[ pyo3:: prelude:: pyfunction]
335
+ fn load_pem_pkcs7_certificates < ' p > (
336
+ py : pyo3:: Python < ' p > ,
337
+ data : & [ u8 ] ,
338
+ ) -> CryptographyResult < & ' p pyo3:: types:: PyList > {
339
+ cfg_if:: cfg_if! {
340
+ if #[ cfg( not( CRYPTOGRAPHY_IS_BORINGSSL ) ) ] {
341
+ let pkcs7_decoded = openssl:: pkcs7:: Pkcs7 :: from_pem( data) . map_err( |_| {
342
+ CryptographyError :: from( pyo3:: exceptions:: PyValueError :: new_err(
343
+ "Unable to parse PKCS7 data" ,
344
+ ) )
345
+ } ) ?;
346
+ load_pkcs7_certificates( py, pkcs7_decoded)
347
+ } else {
348
+ return Err ( CryptographyError :: from(
349
+ exceptions:: UnsupportedAlgorithm :: new_err( (
350
+ "PKCS#7 is not supported by this backend." ,
351
+ exceptions:: Reasons :: UNSUPPORTED_SERIALIZATION ,
352
+ ) ) ,
353
+ ) ) ;
354
+ }
355
+ }
356
+ }
357
+
358
+ #[ pyo3:: prelude:: pyfunction]
359
+ fn load_der_pkcs7_certificates < ' p > (
360
+ py : pyo3:: Python < ' p > ,
361
+ data : & [ u8 ] ,
362
+ ) -> CryptographyResult < & ' p pyo3:: types:: PyList > {
363
+ cfg_if:: cfg_if! {
364
+ if #[ cfg( not( CRYPTOGRAPHY_IS_BORINGSSL ) ) ] {
365
+ let pkcs7_decoded = openssl:: pkcs7:: Pkcs7 :: from_der( data) . map_err( |_| {
366
+ CryptographyError :: from( pyo3:: exceptions:: PyValueError :: new_err(
367
+ "Unable to parse PKCS7 data" ,
368
+ ) )
369
+ } ) ?;
370
+ load_pkcs7_certificates( py, pkcs7_decoded)
371
+ } else {
372
+ return Err ( CryptographyError :: from(
373
+ exceptions:: UnsupportedAlgorithm :: new_err( (
374
+ "PKCS#7 is not supported by this backend." ,
375
+ exceptions:: Reasons :: UNSUPPORTED_SERIALIZATION ,
376
+ ) ) ,
377
+ ) ) ;
378
+ }
379
+ }
380
+ }
381
+
293
382
pub ( crate ) fn create_submodule ( py : pyo3:: Python < ' _ > ) -> pyo3:: PyResult < & pyo3:: prelude:: PyModule > {
294
383
let submod = pyo3:: prelude:: PyModule :: new ( py, "pkcs7" ) ?;
295
384
296
385
submod. add_function ( pyo3:: wrap_pyfunction!( serialize_certificates, submod) ?) ?;
297
386
submod. add_function ( pyo3:: wrap_pyfunction!( sign_and_serialize, submod) ?) ?;
387
+ submod. add_function ( pyo3:: wrap_pyfunction!( load_pem_pkcs7_certificates, submod) ?) ?;
388
+ submod. add_function ( pyo3:: wrap_pyfunction!( load_der_pkcs7_certificates, submod) ?) ?;
298
389
299
390
Ok ( submod)
300
391
}
0 commit comments