Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v0.101.7 preparation #199

Merged
merged 5 commits into from
Oct 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ jobs:
- name: Install toolchain
uses: dtolnay/rust-toolchain@master
with:
toolchain: "1.60"
toolchain: "1.61"
- run: cargo check --lib --all-features

cross:
Expand Down
14 changes: 5 additions & 9 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@
categories = ["cryptography", "no-std"]
description = "Web PKI X.509 Certificate Verification."
edition = "2021"
rust-version = "1.60"
rust-version = "1.61"
license = "ISC"
name = "rustls-webpki"
readme = "README.md"
repository = "https://github.com/rustls/webpki"
version = "0.101.6"
version = "0.101.7"

include = [
"Cargo.toml",
Expand Down Expand Up @@ -67,14 +67,14 @@ alloc = ["ring/alloc"]
std = ["alloc"]

[dependencies]
ring = { version = "0.16.19", default-features = false }
untrusted = "0.7.1"
ring = { version = "0.17", default-features = false }
untrusted = "0.9"

[dev-dependencies]
base64 = "0.21"
bencher = "0.1.5"
once_cell = "1.17.2"
rcgen = { version = "0.11.1", default-features = false }
rcgen = { version = "0.11.3", default-features = false }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"

Expand All @@ -98,7 +98,3 @@ codegen-units = 1
name = "benchmarks"
path = "benches/benchmark.rs"
harness = false

[patch.crates-io]
# TODO(XXX): Remove this once rcgen has cut a release w/ CRL support included.
rcgen = { git = 'https://github.com/est31/rcgen.git', rev = '83e548a06848d923eada1ac66d1a912735b67e79' }
1 change: 1 addition & 0 deletions benches/benchmark.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ fn generate_crl(revoked_count: usize) -> Vec<u8> {
crl_number: SerialNumber::from(1234),
alg: &PKCS_ECDSA_P256_SHA256,
key_identifier_method: KeyIdMethod::Sha256,
issuing_distribution_point: None,
djc marked this conversation as resolved.
Show resolved Hide resolved
revoked_certs,
};
let crl = CertificateRevocationList::from_params(crl).unwrap();
Expand Down
4 changes: 2 additions & 2 deletions src/cert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
use crate::der::Tag;
use crate::signed_data::SignedData;
use crate::x509::{remember_extension, set_extension_once, Extension};
use crate::{der, Error};
use crate::{der, public_values_eq, Error};

/// An enumeration indicating whether a [`Cert`] is a leaf end-entity cert, or a linked
/// list node from the CA `Cert` to a child `Cert` it issued.
Expand Down Expand Up @@ -70,7 +70,7 @@ impl<'a> Cert<'a> {
// TODO: In mozilla::pkix, the comparison is done based on the
// normalized value (ignoring whether or not there is an optional NULL
// parameter for RSA-based algorithms), so this may be too strict.
if signature != signed_data.algorithm {
if !public_values_eq(signature, signed_data.algorithm) {
return Err(Error::SignatureAlgorithmMismatch);
}

Expand Down
4 changes: 2 additions & 2 deletions src/crl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use crate::der::Tag;
use crate::signed_data::{self, SignedData};
use crate::verify_cert::Budget;
use crate::x509::{remember_extension, set_extension_once, Extension};
use crate::{der, Error, SignatureAlgorithm, Time};
use crate::{der, public_values_eq, Error, SignatureAlgorithm, Time};

#[cfg(feature = "alloc")]
use std::collections::HashMap;
Expand Down Expand Up @@ -155,7 +155,7 @@ impl<'a> BorrowedCertRevocationList<'a> {
// This field MUST contain the same algorithm identifier as the
// signatureAlgorithm field in the sequence CertificateList
let signature = der::expect_tag_and_get_value(tbs_cert_list, Tag::Sequence)?;
if signature != signed_data.algorithm {
if !public_values_eq(signature, signed_data.algorithm) {
return Err(Error::SignatureAlgorithmMismatch);
}

Expand Down
22 changes: 12 additions & 10 deletions src/der.rs
Original file line number Diff line number Diff line change
Expand Up @@ -426,8 +426,8 @@ mod tests {

// Only 0x00 and 0xff are accepted values
assert_eq!(
Err(Error::BadDer),
optional_boolean(&mut bytes_reader(&[0x01, 0x01, 0x42]))
optional_boolean(&mut bytes_reader(&[0x01, 0x01, 0x42])).unwrap_err(),
Error::BadDer,
);

// True
Expand All @@ -443,33 +443,35 @@ mod tests {

// Unexpected type
assert_eq!(
Err(Error::BadDer),
bit_string_with_no_unused_bits(&mut bytes_reader(&[0x01, 0x01, 0xff]))
bit_string_with_no_unused_bits(&mut bytes_reader(&[0x01, 0x01, 0xff])).unwrap_err(),
Error::BadDer,
);

// Unexpected nonexistent type
assert_eq!(
Err(Error::BadDer),
bit_string_with_no_unused_bits(&mut bytes_reader(&[0x42, 0xff, 0xff]))
bit_string_with_no_unused_bits(&mut bytes_reader(&[0x42, 0xff, 0xff])).unwrap_err(),
Error::BadDer,
);

// Unexpected empty input
assert_eq!(
Err(Error::BadDer),
bit_string_with_no_unused_bits(&mut bytes_reader(&[]))
bit_string_with_no_unused_bits(&mut bytes_reader(&[])).unwrap_err(),
Error::BadDer,
);

// Valid input with non-zero unused bits
assert_eq!(
Err(Error::BadDer),
bit_string_with_no_unused_bits(&mut bytes_reader(&[0x03, 0x03, 0x04, 0x12, 0x34]))
.unwrap_err(),
Error::BadDer,
);

// Valid input
assert_eq!(
untrusted::Input::from(&[0x12, 0x34]),
bit_string_with_no_unused_bits(&mut bytes_reader(&[0x03, 0x03, 0x00, 0x12, 0x34]))
.unwrap()
.as_slice_less_safe(),
&[0x12, 0x34],
);
}

Expand Down
4 changes: 4 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,7 @@ pub use {
},
subject_name::{DnsName, IpAddr},
};

fn public_values_eq(a: untrusted::Input<'_>, b: untrusted::Input<'_>) -> bool {
a.as_slice_less_safe() == b.as_slice_less_safe()
}
17 changes: 10 additions & 7 deletions src/signed_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

use crate::verify_cert::Budget;
use crate::{der, Error};
use crate::{der, public_values_eq, Error};
use ring::signature;

#[cfg(feature = "alloc")]
Expand Down Expand Up @@ -377,7 +377,7 @@ struct AlgorithmIdentifier {

impl AlgorithmIdentifier {
fn matches_algorithm_id_value(&self, encoded: untrusted::Input) -> bool {
encoded == self.asn1_id_value
public_values_eq(encoded, self.asn1_id_value)
}
}

Expand Down Expand Up @@ -528,10 +528,12 @@ mod tests {
let tsd = parse_test_signed_data(file_contents);
let signature = untrusted::Input::from(&tsd.signature);
assert_eq!(
Err(expected_error),
signature.read_all(Error::BadDer, |input| {
der::bit_string_with_no_unused_bits(input)
})
signature
.read_all(Error::BadDer, |input| {
der::bit_string_with_no_unused_bits(input)
})
.unwrap_err(),
expected_error
);
}

Expand All @@ -549,10 +551,11 @@ mod tests {
let tsd = parse_test_signed_data(file_contents);
let spki = untrusted::Input::from(&tsd.spki);
assert_eq!(
Err(expected_error),
spki.read_all(Error::BadDer, |input| {
der::expect_tag_and_get_value(input, der::Tag::Sequence)
})
.unwrap_err(),
expected_error,
);
}

Expand Down
38 changes: 24 additions & 14 deletions src/verify_cert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ use core::ops::ControlFlow;

use crate::{
cert::{Cert, EndEntityOrCa},
der, signed_data, subject_name, time, CertRevocationList, Error, SignatureAlgorithm,
TrustAnchor,
der, public_values_eq, signed_data, subject_name, time, CertRevocationList, Error,
SignatureAlgorithm, TrustAnchor,
};

pub(crate) struct ChainOptions<'a> {
Expand Down Expand Up @@ -67,7 +67,7 @@ fn build_chain_inner(
opts.trust_anchors,
|trust_anchor: &TrustAnchor| {
let trust_anchor_subject = untrusted::Input::from(trust_anchor.subject);
if cert.issuer != trust_anchor_subject {
if !public_values_eq(cert.issuer, trust_anchor_subject) {
return Err(Error::UnknownIssuer.into());
}

Expand Down Expand Up @@ -101,15 +101,15 @@ fn build_chain_inner(
let potential_issuer =
Cert::from_der(untrusted::Input::from(cert_der), EndEntityOrCa::Ca(cert))?;

if potential_issuer.subject != cert.issuer {
if !public_values_eq(potential_issuer.subject, cert.issuer) {
return Err(Error::UnknownIssuer.into());
}

// Prevent loops; see RFC 4158 section 5.2.
let mut prev = cert;
loop {
if potential_issuer.spki.value() == prev.spki.value()
&& potential_issuer.subject == prev.subject
if public_values_eq(potential_issuer.spki.value(), prev.spki.value())
&& public_values_eq(potential_issuer.subject, prev.subject)
{
return Err(Error::UnknownIssuer.into());
}
Expand Down Expand Up @@ -280,7 +280,7 @@ fn check_crls(
crls: &[&dyn CertRevocationList],
budget: &mut Budget,
) -> Result<Option<CertNotRevoked>, Error> {
assert_eq!(cert.issuer, issuer_subject);
assert!(public_values_eq(cert.issuer, issuer_subject));

let crl = match crls
.iter()
Expand Down Expand Up @@ -500,17 +500,19 @@ impl ExtendedKeyUsage {
}

fn key_purpose_id_equals(&self, value: untrusted::Input<'_>) -> bool {
match self {
ExtendedKeyUsage::Required(eku) => *eku,
ExtendedKeyUsage::RequiredIfPresent(eku) => *eku,
}
.oid_value
== value
public_values_eq(
match self {
ExtendedKeyUsage::Required(eku) => *eku,
ExtendedKeyUsage::RequiredIfPresent(eku) => *eku,
}
.oid_value,
value,
)
}
}

/// An OID value indicating an Extended Key Usage (EKU) key purpose.
#[derive(Clone, Copy, PartialEq, Eq)]
#[derive(Clone, Copy)]
struct KeyPurposeId {
oid_value: untrusted::Input<'static>,
}
Expand All @@ -526,6 +528,14 @@ impl KeyPurposeId {
}
}

impl PartialEq<Self> for KeyPurposeId {
fn eq(&self, other: &Self) -> bool {
public_values_eq(self.oid_value, other.oid_value)
}
}

impl Eq for KeyPurposeId {}

// id-pkix OBJECT IDENTIFIER ::= { 1 3 6 1 5 5 7 }
// id-kp OBJECT IDENTIFIER ::= { id-pkix 3 }

Expand Down
Loading