Skip to content

Commit 2dcf7b6

Browse files
committed
first failing code for certificate verification
1 parent a5b9814 commit 2dcf7b6

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
@@ -1695,6 +1695,12 @@ contain certificates, CRLs, and much more. PKCS7 files commonly have a ``p7b``,
16951695
obtain the signer's certificate by other means (for example from a
16961696
previously signed message).
16971697

1698+
.. attribute:: NoVerify
1699+
1700+
For S/MIME verification only. Don't verify signers certificate. This is
1701+
useful when the signer's certificate is not available or when the signer's
1702+
certificate is not trusted.
1703+
16981704
Serialization Formats
16991705
~~~~~~~~~~~~~~~~~~~~~
17001706

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
@@ -800,7 +800,14 @@ fn verify_der<'p>(
800800
data,
801801
)?;
802802

803-
// TODO: verify the certificates?
803+
// Verify the certificate
804+
if !options.contains(types::PKCS7_NO_VERIFY.get(py)?)? {
805+
let certificates = pyo3::types::PyList::empty(py);
806+
certificates.append(certificate)?;
807+
types::VERIFY_PKCS7_CERTIFICATES
808+
.get(py)?
809+
.call1((certificates,))?;
810+
}
804811
}
805812
_ => {
806813
return Err(CryptographyError::from(
@@ -830,6 +837,18 @@ fn check_verify_options<'p>(
830837
}
831838
}
832839

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

src/rust/src/types.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,10 @@ pub static PKCS7_DETACHED_SIGNATURE: LazyPyImport = LazyPyImport::new(
349349
"cryptography.hazmat.primitives.serialization.pkcs7",
350350
&["PKCS7Options", "DetachedSignature"],
351351
);
352+
pub static PKCS7_NO_VERIFY: LazyPyImport = LazyPyImport::new(
353+
"cryptography.hazmat.primitives.serialization.pkcs7",
354+
&["PKCS7Options", "NoVerify"],
355+
);
352356

353357
pub static SMIME_ENVELOPED_ENCODE: LazyPyImport = LazyPyImport::new(
354358
"cryptography.hazmat.primitives.serialization.pkcs7",
@@ -375,6 +379,11 @@ pub static SMIME_SIGNED_DECODE: LazyPyImport = LazyPyImport::new(
375379
&["_smime_signed_decode"],
376380
);
377381

382+
pub static VERIFY_PKCS7_CERTIFICATES: LazyPyImport = LazyPyImport::new(
383+
"cryptography.hazmat.primitives.serialization.pkcs7",
384+
&["_verify_pkcs7_certificates"],
385+
);
386+
378387
pub static PKCS12KEYANDCERTIFICATES: LazyPyImport = LazyPyImport::new(
379388
"cryptography.hazmat.primitives.serialization.pkcs12",
380389
&["PKCS12KeyAndCertificates"],

tests/hazmat/primitives/test_pkcs7.py

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

927+
def test_pkcs7_verify_der_no_verify(
928+
self, backend, data, certificate, private_key
929+
):
930+
# Signature
931+
builder = (
932+
pkcs7.PKCS7SignatureBuilder()
933+
.set_data(data)
934+
.add_signer(certificate, private_key, hashes.SHA256())
935+
)
936+
signature = builder.sign(serialization.Encoding.DER, [])
937+
938+
# Verification
939+
options = [pkcs7.PKCS7Options.NoVerify]
940+
pkcs7.pkcs7_verify_der(signature, data, certificate, options)
941+
927942
def test_pkcs7_verify_der_no_data(
928943
self, backend, data, certificate, private_key
929944
):

0 commit comments

Comments
 (0)