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

Added support for parsing challenge password attribute in CSR's #129

Merged
merged 15 commits into from
Mar 8, 2023

Conversation

bkstein
Copy link
Contributor

@bkstein bkstein commented Nov 14, 2022

This branch adds support for parsing a challenge password attribute in a CSR.

Please note: rusticata/oid-registry#10 is a prerequisite, as it adds OID_PKCS9_CHALLENGE_PASSWORD. This PR is merged, but not yet released.

@bkstein bkstein marked this pull request as ready for review November 14, 2022 07:39
@bkstein
Copy link
Contributor Author

bkstein commented Nov 14, 2022

A remark @chifflier: I think, the attribute parsing could be improved. Currently, X509CertificationRequest::from_der() parses the CSR and knows the (challenge password) attribute's value. This value is held in X509CriAttribute.parsed_attribute, which is not visible outside the crate:

pub struct X509CriAttribute<'a> {
    pub oid: Oid<'a>,
    pub value: &'a [u8],
    pub(crate) parsed_attribute: ParsedCriAttribute<'a>,
}

Why is that? A user of the x509-parser crate needs to re-parse X509CriAttribute.value instead. I think, the already parsed attribute value should be made available for users. What do you think?

@bkstein
Copy link
Contributor Author

bkstein commented Nov 17, 2022

I just compared CriAttribute to X509Extension and found

impl<'a> X509Extension<'a> {
    ...
    /// Return the extension type or `UnsupportedExtension` if the extension is not implemented.
    #[inline]
    pub fn parsed_extension(&self) -> &ParsedExtension<'a> {
        &self.parsed_extension
    }
}

We could do that in a similar manner for attributes

impl<'a> CriAttribute<'a> {
    ...
    /// Return the attribute type or `UnsupportedAttribute` if the attribute is unknown.
    #[inline]
    pub fn parsed_attribute(&self) -> &ParsedCriAttribute<'a> {
        &self.parsed_attribute
    }
}

@bkstein bkstein marked this pull request as draft November 17, 2022 07:13
@bkstein
Copy link
Contributor Author

bkstein commented Nov 17, 2022

I will check my proposal and set this request to draft.

@bkstein
Copy link
Contributor Author

bkstein commented Nov 17, 2022

Seems to work.

@bkstein bkstein marked this pull request as ready for review November 17, 2022 07:44
@bkstein
Copy link
Contributor Author

bkstein commented Dec 1, 2022

@chifflier The checks will fail until oid-registry with OID for challenge password is released.

@chifflier
Copy link
Member

@chifflier The checks will fail until oid-registry with OID for challenge password is released.

oid-registry 0.6.1 has just been released with the required OID

Comment on lines 129 to 130
// I'm sure, there is a more elegant way to try multiple parsers until the first succeeds,
// but I don't know nom well enough to implement it.
Copy link
Member

@chifflier chifflier Dec 12, 2022

Choose a reason for hiding this comment

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

The nom parser for this is alt so I supposed the code below can be rewritten as something like alt(parse_der_utf8string, parse_der_printablestring).
Example:

x509-parser/src/x509.rs

Lines 153 to 155 in f6d25f6

fn parse_attribute_value(i: &[u8]) -> ParseResult<Any, Error> {
alt((Any::from_der, parse_malformed_string))(i)
}

Copy link
Member

@chifflier chifflier left a comment

Choose a reason for hiding this comment

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

Overall the PR looks fine, thanks!
Can you rebase to the latest master (now that oid-registry is released) and address the minor point in comment before merge?

Comment on lines 140 to 141
match obj.content {
BerObjectContent::PrintableString(s) | BerObjectContent::UTF8String(s) => {
Copy link
Member

Choose a reason for hiding this comment

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

I think something like

match obj.as_str() {
    Ok(s) => Ok((rem, ChallengePassword { 0: s.to_string() })),
    // ...

is slightly more elegant and does not require to enumerate variants

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Got it, thanks. However, digging into RFC 2985, 5.2.2 I saw, that all string types should be supported (not only the recommended PrintableString and UTF8String). I extended the parser with the other types using nom::branch::alt.

tests/readcsr.rs Outdated
Comment on lines 78 to 79
let (i, challenge_password) = String::from_der(i)?;
Ok((i, challenge_password))
Copy link
Member

Choose a reason for hiding this comment

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

Isn't that exactly the same as just String::from_der(i) ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, I think your right. I'll fix that.

@bkstein
Copy link
Contributor Author

bkstein commented Dec 12, 2022

Changes are implemented. Thanks for reviewing!

src/cri_attributes.rs Outdated Show resolved Hide resolved
Copy link
Member

@chifflier chifflier left a comment

Choose a reason for hiding this comment

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

Looks great now, thanks for your patience!
I will merge it as soon as possible

@chifflier chifflier merged commit ada75cf into rusticata:master Mar 8, 2023
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.

None yet

2 participants