sfackler / rust-openssl

OpenSSL bindings for Rust
1.39k stars 742 forks source link

Read x509 Extensions #373

Open dbrgn opened 8 years ago

dbrgn commented 8 years ago

Is there already support for reading x509 extensions from an existing certificate? In my case I need to be able to read the X509v3 Authority Key Identifier.

sfackler commented 8 years ago

I've just recently added support for access to subject alt names. Each extension needs specific handling unfortunately, but a PR to add accessors for Authority Key Identifiers would be great!

ignatenkobrain commented 7 years ago

This would be nice to have definitely since I need it in my project ;)

ignatenkobrain commented 6 years ago

@sfackler Any news here? it's almost 2 years =(

sfackler commented 6 years ago

Pull requests welcome! I'm probably not going to have a chance to do it myself in the near term.

ignatenkobrain commented 6 years ago

My opensslFu is in very bad shape, last time I was using openssl to get some x509/asn stuff I got headache. So I'm not the one who can send PR unfortunately =(

landaire commented 5 years ago

I came across this while looking for support for getting extended key usage. I've never interfaced with the OpenSSL APIs before, but I added the functions required for getting arbitrary extension data here: https://github.com/landaire/rust-openssl/commit/612c1e9e8075a161fb61f7e3aea7749df3e19b77

I'm not exactly sure what the correct way to implement this specific request would be. OpenSSL does not expose APIs that wrap as getters for the AUTHORITY_KEYID fields from what I can tell. If there were I think the solution would be:

  1. Create AuthorityKeyId and AuthorityKeyIdRef structs and write wrapper methods for the keyid, issuer, and serial fields as defined here.functions that provide you with these fields.
  2. X509_get_ext_d2i(x, ffi::NID_authority_key_identifier, null_mut, null_mut)
  3. Return the result as an AuthorityKeyIdRef

Since this isn't the case, I'm not sure what other OpenSSL APIs are available for extracting this data. X509_EXTENSION_get_data looks like it may be the right approach to decode an ASN1_STRING, GENERAL_NAMES, and ASN1_INTEGER, but I'm unsure.

ignatenkobrain commented 5 years ago

https://github.com/rpm-software-management/librhsm/blob/master/rhsm/rhsm-product-certificate.c#L86

This is the code I'm using now in C.

landaire commented 5 years ago

Thanks @ignatenkobrain. I think the correct approach here is to add methods to the X509ExtensionRef struct for grabbing object(), critical(), and data() as wrappers for methods here (I actually already did this then deleted that working assuming it wasn't needed, oops). Then specific extensions can repeatedly call ASN1_get_object for each of their fields until the data is fully decoded or an error occurs.

So in the case of AUTHORITY_KEYID the general flow would be:

  1. Get the X509Extension
  2. Use X509_EXTENSION_get_data to get the encoded data
  3. Call ASN1_get_object, providing the address of the beginning of the extension data and check type is ASN1_OCTET_STRING for the keyid field
  4. Call ASN1_get_object, providing the address of extension data + length of keyid and check type is GENERAL_NAMES for the issuer field
  5. Call ASN1_get_object, providing the address of extension data + length of key id + length of issuer and check type is ASN1_INTEGER for the serial field

Does that sound correct? Like I said, I've never interfaced with OpenSSL APIs before so I'm trying to make sure I understand this before writing up an implementation.

landaire commented 5 years ago

Ok, this is done as part of https://github.com/landaire/rust-openssl/commit/ce83a0a55873ced62da6dc41a389366611019d68 and appears to be working. The tests are lacking for validation since calculating the key ID myself requires a SHA1 digest over the public key and I'm too lazy to write bindings for the SHA_* functions to do this without introducing new crates... but manual analysis shows this working fine.

sfackler commented 5 years ago

@landaire SHA bindings are over here: https://docs.rs/openssl/0.10.20/openssl/sha/fn.sha1.html

landaire commented 5 years ago

PR is here: https://github.com/sfackler/rust-openssl/pull/1095

Feedback is much appreciated.