@@ -673,13 +673,12 @@ fn compute_pkcs7_signature_algorithm<'p>(
673
673
}
674
674
675
675
#[ pyo3:: pyfunction]
676
- #[ pyo3( signature = ( signature, content = None , certificate = None , options = None ) ) ]
676
+ #[ pyo3( signature = ( signature, content = None , certificate = None ) ) ]
677
677
fn verify_smime < ' p > (
678
678
py : pyo3:: Python < ' p > ,
679
679
signature : & [ u8 ] ,
680
680
content : Option < & [ u8 ] > ,
681
681
certificate : Option < pyo3:: Bound < ' p , x509:: certificate:: Certificate > > ,
682
- options : Option < & pyo3:: Bound < ' p , pyo3:: types:: PyList > > ,
683
682
) -> CryptographyResult < ( ) > {
684
683
// Parse the email
685
684
let py_content_and_signature = types:: SMIME_SIGNED_DECODE . get ( py) ?. call1 ( ( signature, ) ) ?;
@@ -703,17 +702,16 @@ fn verify_smime<'p>(
703
702
}
704
703
} ;
705
704
706
- verify_der ( py, signature, content, certificate, options )
705
+ verify_der ( py, signature, content, certificate)
707
706
}
708
707
709
708
#[ pyo3:: pyfunction]
710
- #[ pyo3( signature = ( signature, content = None , certificate = None , options = None ) ) ]
709
+ #[ pyo3( signature = ( signature, content = None , certificate = None ) ) ]
711
710
fn verify_pem < ' p > (
712
711
py : pyo3:: Python < ' p > ,
713
712
signature : & [ u8 ] ,
714
713
content : Option < & [ u8 ] > ,
715
714
certificate : Option < pyo3:: Bound < ' p , x509:: certificate:: Certificate > > ,
716
- options : Option < & pyo3:: Bound < ' p , pyo3:: types:: PyList > > ,
717
715
) -> CryptographyResult < ( ) > {
718
716
let pem_str = std:: str:: from_utf8 ( signature)
719
717
. map_err ( |_| pyo3:: exceptions:: PyValueError :: new_err ( "Invalid PEM data" ) ) ?;
@@ -729,25 +727,17 @@ fn verify_pem<'p>(
729
727
) ) ;
730
728
}
731
729
732
- verify_der ( py, & pem. into_contents ( ) , content, certificate, options )
730
+ verify_der ( py, & pem. into_contents ( ) , content, certificate)
733
731
}
734
732
735
733
#[ pyo3:: pyfunction]
736
- #[ pyo3( signature = ( signature, content = None , certificate = None , options = None ) ) ]
734
+ #[ pyo3( signature = ( signature, content = None , certificate = None ) ) ]
737
735
fn verify_der < ' p > (
738
736
py : pyo3:: Python < ' p > ,
739
737
signature : & [ u8 ] ,
740
738
content : Option < & [ u8 ] > ,
741
739
certificate : Option < pyo3:: Bound < ' p , x509:: certificate:: Certificate > > ,
742
- options : Option < & pyo3:: Bound < ' p , pyo3:: types:: PyList > > ,
743
740
) -> CryptographyResult < ( ) > {
744
- // Check the verify options
745
- let options = match options {
746
- Some ( options) => Cow :: Borrowed ( options) ,
747
- None => Cow :: Owned ( pyo3:: types:: PyList :: empty ( py) ) ,
748
- } ;
749
- check_verify_options ( py, & options) ?;
750
-
751
741
// Verify the data
752
742
let content_info = asn1:: parse_single :: < pkcs7:: ContentInfo < ' _ > > ( signature) ?;
753
743
match content_info. content {
@@ -793,88 +783,84 @@ fn verify_der<'p>(
793
783
794
784
// Get recipients, and find the one matching with the signer infos (if any)
795
785
// TODO: what to do for multiple certificates?
796
- if !options. contains ( types:: PKCS7_NO_SIGS . get ( py) ?) ? {
797
- let mut signer_infos = signed_data. signer_infos . unwrap_read ( ) . clone ( ) ;
798
- let signer_certificate = certificate. get ( ) . raw . borrow_dependent ( ) ;
799
- let signer_serial_number = signer_certificate. tbs_cert . serial ;
800
- let signer_issuer = signer_certificate. tbs_cert . issuer . clone ( ) ;
801
- let found_signer_info = signer_infos. find ( |info| {
802
- info. issuer_and_serial_number . serial_number == signer_serial_number
803
- && info. issuer_and_serial_number . issuer == signer_issuer
804
- } ) ;
786
+ let mut signer_infos = signed_data. signer_infos . unwrap_read ( ) . clone ( ) ;
787
+ let signer_certificate = certificate. get ( ) . raw . borrow_dependent ( ) ;
788
+ let signer_serial_number = signer_certificate. tbs_cert . serial ;
789
+ let signer_issuer = signer_certificate. tbs_cert . issuer . clone ( ) ;
790
+ let found_signer_info = signer_infos. find ( |info| {
791
+ info. issuer_and_serial_number . serial_number == signer_serial_number
792
+ && info. issuer_and_serial_number . issuer == signer_issuer
793
+ } ) ;
805
794
806
- // Raise error when no signer is found
807
- let signer_info = match found_signer_info {
808
- Some ( info) => info,
809
- None => {
810
- return Err ( CryptographyError :: from (
811
- pyo3:: exceptions:: PyValueError :: new_err (
812
- "No signer found that matches the given certificate." ,
813
- ) ,
814
- ) ) ;
815
- }
816
- } ;
817
-
818
- // Prepare the content: try to use the authenticated attributes, then the content stored
819
- // in the signed data, then the provided content. If None of these are available, raise
820
- // an error. TODO: what should the order be?
821
- let data = match signer_info. authenticated_attributes {
822
- Some ( attrs) => Cow :: Owned ( asn1:: write_single ( & attrs) ?) ,
823
- None => match content {
824
- Some ( data) => Cow :: Borrowed ( data) ,
825
- None => match signed_data. content_info . content {
826
- pkcs7:: Content :: Data ( Some ( data) ) => Cow :: Borrowed ( data. into_inner ( ) ) ,
827
- _ => {
828
- return Err ( CryptographyError :: from (
829
- pyo3:: exceptions:: PyValueError :: new_err (
830
- "No content stored in the signature or provided." ,
831
- ) ,
832
- ) ) ;
833
- }
834
- } ,
835
- } ,
836
- } ;
837
-
838
- // For RSA signatures (with no PSS padding), the OID is always the same no matter the
839
- // digest algorithm. We need to modify the algorithm identifier to add the hash
840
- // algorithm information. We are checking for RSA-256, which the S/MIME v3.2 RFC
841
- // specifies as MUST support (https://datatracker.ietf.org/doc/html/rfc5751#section-2.2)
842
- let signature_algorithm = match signer_info. digest_encryption_algorithm . oid ( ) {
843
- & oid:: RSA_OID => match signer_info. digest_algorithm . oid ( ) {
844
- & oid:: SHA256_OID => common:: AlgorithmIdentifier {
845
- oid : asn1:: DefinedByMarker :: marker ( ) ,
846
- params : common:: AlgorithmParameters :: RsaWithSha256 ( Some ( ( ) ) ) ,
847
- } ,
795
+ // Raise error when no signer is found
796
+ let signer_info = match found_signer_info {
797
+ Some ( info) => info,
798
+ None => {
799
+ return Err ( CryptographyError :: from (
800
+ pyo3:: exceptions:: PyValueError :: new_err (
801
+ "No signer found that matches the given certificate." ,
802
+ ) ,
803
+ ) ) ;
804
+ }
805
+ } ;
806
+
807
+ // Prepare the content: try to use the authenticated attributes, then the content stored
808
+ // in the signed data, then the provided content. If None of these are available, raise
809
+ // an error. TODO: what should the order be?
810
+ let data = match signer_info. authenticated_attributes {
811
+ Some ( attrs) => Cow :: Owned ( asn1:: write_single ( & attrs) ?) ,
812
+ None => match content {
813
+ Some ( data) => Cow :: Borrowed ( data) ,
814
+ None => match signed_data. content_info . content {
815
+ pkcs7:: Content :: Data ( Some ( data) ) => Cow :: Borrowed ( data. into_inner ( ) ) ,
848
816
_ => {
849
817
return Err ( CryptographyError :: from (
850
- exceptions:: UnsupportedAlgorithm :: new_err ( (
851
- "Only SHA-256 is currently supported for content verification with RSA." ,
852
- exceptions:: Reasons :: UNSUPPORTED_SERIALIZATION ,
853
- ) ) ,
854
- ) )
818
+ pyo3:: exceptions:: PyValueError :: new_err (
819
+ "No content stored in the signature or provided." ,
820
+ ) ,
821
+ ) ) ;
855
822
}
856
823
} ,
857
- _ => signer_info. digest_encryption_algorithm ,
858
- } ;
859
-
860
- // Verify the signature
861
- x509:: sign:: verify_signature_with_signature_algorithm (
862
- py,
863
- certificate. call_method0 ( pyo3:: intern!( py, "public_key" ) ) ?,
864
- & signature_algorithm,
865
- signer_info. encrypted_digest ,
866
- & data,
867
- ) ?;
868
- }
824
+ } ,
825
+ } ;
826
+
827
+ // For RSA signatures (with no PSS padding), the OID is always the same no matter the
828
+ // digest algorithm. We need to modify the algorithm identifier to add the hash
829
+ // algorithm information. We are checking for RSA-256, which the S/MIME v3.2 RFC
830
+ // specifies as MUST support (https://datatracker.ietf.org/doc/html/rfc5751#section-2.2)
831
+ let signature_algorithm = match signer_info. digest_encryption_algorithm . oid ( ) {
832
+ & oid:: RSA_OID => match signer_info. digest_algorithm . oid ( ) {
833
+ & oid:: SHA256_OID => common:: AlgorithmIdentifier {
834
+ oid : asn1:: DefinedByMarker :: marker ( ) ,
835
+ params : common:: AlgorithmParameters :: RsaWithSha256 ( Some ( ( ) ) ) ,
836
+ } ,
837
+ _ => {
838
+ return Err ( CryptographyError :: from (
839
+ exceptions:: UnsupportedAlgorithm :: new_err ( (
840
+ "Only SHA-256 is currently supported for content verification with RSA." ,
841
+ exceptions:: Reasons :: UNSUPPORTED_SERIALIZATION ,
842
+ ) ) ,
843
+ ) )
844
+ }
845
+ } ,
846
+ _ => signer_info. digest_encryption_algorithm ,
847
+ } ;
848
+
849
+ // Verify the signature
850
+ x509:: sign:: verify_signature_with_signature_algorithm (
851
+ py,
852
+ certificate. call_method0 ( pyo3:: intern!( py, "public_key" ) ) ?,
853
+ & signature_algorithm,
854
+ signer_info. encrypted_digest ,
855
+ & data,
856
+ ) ?;
869
857
870
858
// Verify the certificate
871
- if !options. contains ( types:: PKCS7_NO_VERIFY . get ( py) ?) ? {
872
- let certificates = pyo3:: types:: PyList :: empty ( py) ;
873
- certificates. append ( certificate) ?;
874
- types:: VERIFY_PKCS7_CERTIFICATES
875
- . get ( py) ?
876
- . call1 ( ( certificates, ) ) ?;
877
- }
859
+ let certificates = pyo3:: types:: PyList :: empty ( py) ;
860
+ certificates. append ( certificate) ?;
861
+ types:: VERIFY_PKCS7_CERTIFICATES
862
+ . get ( py) ?
863
+ . call1 ( ( certificates, ) ) ?;
878
864
}
879
865
_ => {
880
866
return Err ( CryptographyError :: from (
@@ -888,38 +874,6 @@ fn verify_der<'p>(
888
874
Ok ( ( ) )
889
875
}
890
876
891
- fn check_verify_options < ' p > (
892
- py : pyo3:: Python < ' p > ,
893
- options : & pyo3:: Bound < ' p , pyo3:: types:: PyList > ,
894
- ) -> Result < ( ) , CryptographyError > {
895
- // Check if all options are from the PKCS7Options enum
896
- let pkcs7_options = types:: PKCS7_OPTIONS . get ( py) ?;
897
- for opt in options. iter ( ) {
898
- if !opt. is_instance ( & pkcs7_options) ? {
899
- return Err ( CryptographyError :: from (
900
- pyo3:: exceptions:: PyValueError :: new_err (
901
- "options must be from the PKCS7Options enum" ,
902
- ) ,
903
- ) ) ;
904
- }
905
- }
906
-
907
- // Check if any option is not PKCS7Options::NoVerify
908
- let no_verify_option = types:: PKCS7_NO_VERIFY . get ( py) ?;
909
- let no_sigs_option = types:: PKCS7_NO_SIGS . get ( py) ?;
910
- for opt in options. iter ( ) {
911
- if opt. ne ( no_verify_option. clone ( ) ) ? & opt. ne ( no_sigs_option. clone ( ) ) ? {
912
- return Err ( CryptographyError :: from (
913
- pyo3:: exceptions:: PyValueError :: new_err (
914
- "Only the following options are supported for verification: NoVerify, NoSigs" ,
915
- ) ,
916
- ) ) ;
917
- }
918
- }
919
-
920
- Ok ( ( ) )
921
- }
922
-
923
877
fn smime_canonicalize ( data : & [ u8 ] , text_mode : bool ) -> ( Cow < ' _ , [ u8 ] > , Cow < ' _ , [ u8 ] > ) {
924
878
let mut new_data_with_header = vec ! [ ] ;
925
879
let mut new_data_without_header = vec ! [ ] ;
0 commit comments