Skip to content

Commit e202bbf

Browse files
committed
first failing code for certificate verification
1 parent 41c3a33 commit e202bbf

File tree

5 files changed

+57
-1
lines changed

5 files changed

+57
-1
lines changed

docs/hazmat/primitives/asymmetric/serialization.rst

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

1784+
.. attribute:: NoVerify
1785+
1786+
For S/MIME verification only. Don't verify signers certificate. This is
1787+
useful when the signer's certificate is not available or when the signer's
1788+
certificate is not trusted.
1789+
17841790
Serialization Formats
17851791
~~~~~~~~~~~~~~~~~~~~~
17861792

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ class PKCS7Options(utils.Enum):
5858
NoCapabilities = "Don't embed SMIME capabilities"
5959
NoAttributes = "Don't embed authenticatedAttributes"
6060
NoCerts = "Don't embed signer certificate"
61+
NoVerify = "Don't verify signers certificate"
6162

6263

6364
def pkcs7_x509_extension_policies() -> tuple[ExtensionPolicy, ExtensionPolicy]:
@@ -511,6 +512,12 @@ def _smime_signed_decode(data: bytes) -> tuple[bytes | None, bytes]:
511512
raise ValueError("Not an S/MIME signed message")
512513

513514

515+
def _verify_pkcs7_certificates(certificates: list[x509.Certificate]) -> None:
516+
builder = PolicyBuilder().store(Store(certificates))
517+
verifier = builder.build_client_verifier()
518+
verifier.verify(certificates[0], certificates[1:])
519+
520+
514521
def _smime_enveloped_encode(data: bytes) -> bytes:
515522
m = email.message.Message()
516523
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
@@ -353,6 +353,10 @@ pub static PKCS7_DETACHED_SIGNATURE: LazyPyImport = LazyPyImport::new(
353353
"cryptography.hazmat.primitives.serialization.pkcs7",
354354
&["PKCS7Options", "DetachedSignature"],
355355
);
356+
pub static PKCS7_NO_VERIFY: LazyPyImport = LazyPyImport::new(
357+
"cryptography.hazmat.primitives.serialization.pkcs7",
358+
&["PKCS7Options", "NoVerify"],
359+
);
356360

357361
pub static SMIME_ENVELOPED_ENCODE: LazyPyImport = LazyPyImport::new(
358362
"cryptography.hazmat.primitives.serialization.pkcs7",
@@ -379,6 +383,11 @@ pub static SMIME_SIGNED_DECODE: LazyPyImport = LazyPyImport::new(
379383
&["_smime_signed_decode"],
380384
);
381385

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

tests/hazmat/primitives/test_pkcs7.py

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

1085+
def test_pkcs7_verify_der_no_verify(
1086+
self, backend, data, certificate, private_key
1087+
):
1088+
# Signature
1089+
builder = (
1090+
pkcs7.PKCS7SignatureBuilder()
1091+
.set_data(data)
1092+
.add_signer(certificate, private_key, hashes.SHA256())
1093+
)
1094+
signature = builder.sign(serialization.Encoding.DER, [])
1095+
1096+
# Verification
1097+
options = [pkcs7.PKCS7Options.NoVerify]
1098+
pkcs7.pkcs7_verify_der(signature, data, certificate, options)
1099+
10851100
def test_pkcs7_verify_der_no_data(
10861101
self, backend, data, certificate, private_key
10871102
):

0 commit comments

Comments
 (0)