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

x501+x509: CertificateDocument, X509Version, and more additions #393

Closed
wants to merge 20 commits into from

Conversation

carl-wallace
Copy link
Contributor

Modifications resulting from code review of changes to yubikey library and client tool to use x509 crate:

  • moved additional OID definitions from certval into x509
  • moved, refactored and expanded OID lookup function
  • added CertificateDocument implementation
  • added X509Version enum and improved decode and encode for TBSCertificate relative to version-specific fields

x501/src/time.rs Outdated Show resolved Hide resolved
x509/src/certificate.rs Outdated Show resolved Hide resolved
@tarcieri tarcieri changed the title Yubikey mods x501+x509: CertificateDocument, X509Version, and more additions Feb 7, 2022
@@ -25,6 +28,57 @@ pub fn default_zero() -> u32 {
/// Version ::= INTEGER { v1(0), v2(1), v3(2) }
pub const X509_CERT_VERSION: u8 = 2;

/// Version identifier for X.509 certificates. In practice, only v3 is used.
#[derive(Clone, Debug, Copy, PartialEq, Eq, PartialOrd)]
pub enum X509Version {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the spirit of RFC356 I'd suggest simply calling this Version.

That also follows the convention used by other version types in this repo.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok. will change as i mop up cargo hack findings.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#410 allows you to derive this type.

x509/src/certificate.rs Outdated Show resolved Hide resolved
x509/src/certificate.rs Outdated Show resolved Hide resolved
x509/src/certificate.rs Outdated Show resolved Hide resolved
x509/src/certificate.rs Outdated Show resolved Hide resolved
#[allow(unused_imports)]
use core::convert::TryFrom;
f(&[
&ContextSpecific {
tag_number: VERSION_TAG,
tag_mode: TagMode::Explicit,
value: self.version,
value: version_value,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like just self.version should work here, especially if you make it Copy

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed here (initially I though you meant replace that production with self.version but landed as shown): carl-wallace@c226d37

x509/src/certificate.rs Outdated Show resolved Hide resolved
@npmccallum
Copy link
Contributor

@tarcieri I would like to review this after my derive fixes and other cleanup has been merged.

/// it will parse successfully according to this crate's parsing rules.
#[derive(Clone)]
#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
pub struct CertificateDocument(Vec<u8>);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tarcieri I know I've implemented one of these document types for pkcs10. However:

  1. What is the purpose of them? I don't understand how they are intended to be used. It seems that PEM decoding is implemented through the document types. However, in order to instantiate a document, you have to fully parse the DER. So why not just have the fully parsed type?

  2. If there is a good reason for the document types, surely these can be genericized. They are all exactly the same code and differ only by the type of the value decoded therein. So Document<T: Decodable + Encodable> seems like an obvious win here.

Copy link
Member

@tarcieri tarcieri Feb 11, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like a complicated and important enough issue I did a long-form write up on it, so as not to lose the answers to these questions in a PR comment: #421

Some short answers though:

  1. The purpose of these types is discussed at length in der: *Document type improvements #421, but in regard to PEM specifically, since Decode<'a> is zero-copy and needs to borrow from a slice containing DER, parsing PEM needs to decode DER into a buffer that Decode<'a> can borrow from. If we had something like DecodeOwned which didn't need to borrow, documents could be decoded directly from PEM. As it were, this is how the ssh-key crate works, and I just added support for incremental/buffered PEM decoding to the pem-rfc7468 crate (pem-rfc7468: buffered Base64 decoder #406) and changed the ssh-key crate to use that (ssh-key: use pem-rfc7468 for private key PEM parser #407). But that only works because the ssh-key crate is built entirely around owned types (and doesn't use ASN.1 DER).

  2. The problem with Document<T: Decodable + Encodable> is you omitted the lifetime on Decodable<'a>. Since it's a 'self borrow and Rust doesn't actually have a way to notate a 'self lifetime you can't notate that on a struct definition, however as I noted in der: *Document type improvements #421 it can probably be done by moving the bounds to individual methods so Decodable<'a> can hang off pub fn decode<'a>(&'a self) -> T where T: Decode<'a>

_ => Err(Self::TAG.value_error()),
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@carl-wallace All the changes in this file are obsolete if we merge #410 instead.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure. Further review of this until after alignment with changes to dependencies is likely not worthwhile.

/// id-sha512 OBJECT IDENTIFIER ::=
/// { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101)
/// csor(3) algorithms(4) hashalgs(2) 3 }
pub const PKIXALG_SHA512: ObjectIdentifier = ObjectIdentifier::new("2.16.840.1.101.3.4.2.3");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really don't like the "big pile of OID constants" approach. There has to be a way to organize these better.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The OIDs are grouped by module with names derived by capitalization, insertion of underscores and addition of a prefix. I'm OK with this approach, but if there is something desired please let me know.

PKIXALG_SHA512 => "sha512",
_ => "",
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really don't like this function. It smells like OpenSSL. What is the purpose of it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Logging and display.


pub fn default_zero_u8() -> u8 {
0
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please don't. Use Default::default.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As part of the realignment as noted above.

@carl-wallace
Copy link
Contributor Author

outdated

@carl-wallace carl-wallace deleted the yubikey_mods branch January 23, 2023 13:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants