Skip to content

Commit edc74c1

Browse files
committed
first failing code for certificate verification
1 parent d70307f commit edc74c1

File tree

5 files changed

+58
-1
lines changed

5 files changed

+58
-1
lines changed

docs/hazmat/primitives/asymmetric/serialization.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1708,6 +1708,12 @@ contain certificates, CRLs, and much more. PKCS7 files commonly have a ``p7b``,
17081708
obtain the signer's certificate by other means (for example from a
17091709
previously signed message).
17101710

1711+
.. attribute:: NoVerify
1712+
1713+
For S/MIME verification only. Don't verify signers certificate. This is
1714+
useful when the signer's certificate is not available or when the signer's
1715+
certificate is not trusted.
1716+
17111717
Serialization Formats
17121718
~~~~~~~~~~~~~~~~~~~~~
17131719

src/cryptography/hazmat/primitives/serialization/pkcs7.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
algorithms,
2222
)
2323
from cryptography.utils import _check_byteslike
24+
from cryptography.x509.verification import PolicyBuilder, Store
2425

2526
load_pem_pkcs7_certificates = rust_pkcs7.load_pem_pkcs7_certificates
2627

@@ -51,6 +52,7 @@ class PKCS7Options(utils.Enum):
5152
NoCapabilities = "Don't embed SMIME capabilities"
5253
NoAttributes = "Don't embed authenticatedAttributes"
5354
NoCerts = "Don't embed signer certificate"
55+
NoVerify = "Don't verify signers certificate"
5456

5557

5658
class PKCS7SignatureBuilder:
@@ -390,6 +392,12 @@ def _smime_signed_decode(data: bytes) -> tuple[bytes | None, bytes]:
390392
raise ValueError("Not an S/MIME signed message")
391393

392394

395+
def _verify_pkcs7_certificates(certificates: list[x509.Certificate]) -> None:
396+
builder = PolicyBuilder().store(Store(certificates))
397+
verifier = builder.build_client_verifier()
398+
verifier.verify(certificates[0], certificates[1:])
399+
400+
393401
def _smime_enveloped_encode(data: bytes) -> bytes:
394402
m = email.message.Message()
395403
m.add_header("MIME-Version", "1.0")

src/rust/src/pkcs7.rs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -804,7 +804,14 @@ fn verify_der<'p>(
804804
data,
805805
)?;
806806

807-
// TODO: verify the certificates?
807+
// Verify the certificate
808+
if !options.contains(types::PKCS7_NO_VERIFY.get(py)?)? {
809+
let certificates = pyo3::types::PyList::empty(py);
810+
certificates.append(certificate)?;
811+
types::VERIFY_PKCS7_CERTIFICATES
812+
.get(py)?
813+
.call1((certificates,))?;
814+
}
808815
}
809816
_ => {
810817
return Err(CryptographyError::from(
@@ -834,6 +841,18 @@ fn check_verify_options<'p>(
834841
}
835842
}
836843

844+
// Check if any option is not PKCS7Options::NoVerify
845+
let no_verify_option = types::PKCS7_NO_VERIFY.get(py)?;
846+
for opt in options.iter() {
847+
if !opt.eq(no_verify_option.clone())? {
848+
return Err(CryptographyError::from(
849+
pyo3::exceptions::PyValueError::new_err(
850+
"Only the following options are supported for verification: NoVerify",
851+
),
852+
));
853+
}
854+
}
855+
837856
Ok(())
838857
}
839858

src/rust/src/types.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,10 @@ pub static PKCS7_DETACHED_SIGNATURE: LazyPyImport = LazyPyImport::new(
354354
"cryptography.hazmat.primitives.serialization.pkcs7",
355355
&["PKCS7Options", "DetachedSignature"],
356356
);
357+
pub static PKCS7_NO_VERIFY: LazyPyImport = LazyPyImport::new(
358+
"cryptography.hazmat.primitives.serialization.pkcs7",
359+
&["PKCS7Options", "NoVerify"],
360+
);
357361

358362
pub static SMIME_ENVELOPED_ENCODE: LazyPyImport = LazyPyImport::new(
359363
"cryptography.hazmat.primitives.serialization.pkcs7",
@@ -380,6 +384,11 @@ pub static SMIME_SIGNED_DECODE: LazyPyImport = LazyPyImport::new(
380384
&["_smime_signed_decode"],
381385
);
382386

387+
pub static VERIFY_PKCS7_CERTIFICATES: LazyPyImport = LazyPyImport::new(
388+
"cryptography.hazmat.primitives.serialization.pkcs7",
389+
&["_verify_pkcs7_certificates"],
390+
);
391+
383392
pub static PKCS12KEYANDCERTIFICATES: LazyPyImport = LazyPyImport::new(
384393
"cryptography.hazmat.primitives.serialization.pkcs12",
385394
&["PKCS12KeyAndCertificates"],

tests/hazmat/primitives/test_pkcs7.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -939,6 +939,21 @@ def test_pkcs7_verify_der_no_content(
939939
# Verification
940940
pkcs7.pkcs7_verify_der(signature, None, certificate, [])
941941

942+
def test_pkcs7_verify_der_no_verify(
943+
self, backend, data, certificate, private_key
944+
):
945+
# Signature
946+
builder = (
947+
pkcs7.PKCS7SignatureBuilder()
948+
.set_data(data)
949+
.add_signer(certificate, private_key, hashes.SHA256())
950+
)
951+
signature = builder.sign(serialization.Encoding.DER, [])
952+
953+
# Verification
954+
options = [pkcs7.PKCS7Options.NoVerify]
955+
pkcs7.pkcs7_verify_der(signature, data, certificate, options)
956+
942957
def test_pkcs7_verify_der_no_data(
943958
self, backend, data, certificate, private_key
944959
):

0 commit comments

Comments
 (0)