From 5bb89d7552fd5fd14749769da8e848ee67ef7582 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ren=C3=A9=20Richter?= <richterrettich@gmail.com>
Date: Sat, 21 Apr 2018 09:44:49 +0200
Subject: [PATCH] Add functions to X509Req to obtain public key and extensions

This allows for basic CSR signing.
---
 openssl-sys/src/lib.rs    |  2 ++
 openssl/src/x509/mod.rs   | 22 ++++++++++++++++++++++
 openssl/src/x509/tests.rs |  4 ++++
 3 files changed, 28 insertions(+)

diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs
index 85527f8f5..03ab60f41 100644
--- a/openssl-sys/src/lib.rs
+++ b/openssl-sys/src/lib.rs
@@ -2741,8 +2741,10 @@ extern "C" {
     pub fn X509_REQ_set_version(req: *mut X509_REQ, version: c_long) -> c_int;
     pub fn X509_REQ_set_subject_name(req: *mut X509_REQ, name: *mut X509_NAME) -> c_int;
     pub fn X509_REQ_set_pubkey(req: *mut X509_REQ, pkey: *mut EVP_PKEY) -> c_int;
+    pub fn X509_REQ_get_pubkey(req: *mut X509_REQ) -> *mut EVP_PKEY;
     pub fn X509_REQ_add_extensions(req: *mut X509_REQ, exts: *mut stack_st_X509_EXTENSION)
         -> c_int;
+    pub fn X509_REQ_get_extensions(req: *mut X509_REQ) -> *mut stack_st_X509_EXTENSION;
     pub fn X509_REQ_sign(x: *mut X509_REQ, pkey: *mut EVP_PKEY, md: *const EVP_MD) -> c_int;
 
     #[cfg(not(ossl101))]
diff --git a/openssl/src/x509/mod.rs b/openssl/src/x509/mod.rs
index 011a2d962..c1ae3b16f 100644
--- a/openssl/src/x509/mod.rs
+++ b/openssl/src/x509/mod.rs
@@ -1069,6 +1069,28 @@ impl X509ReqRef {
             X509NameRef::from_ptr(name)
         }
     }
+
+    /// Returns the public key of the certificate request.
+    ///
+    /// This corresponds to [`X509_REQ_get_pubkey"]
+    ///
+    /// [`X509_REQ_get_pubkey`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_REQ_get_pubkey.html
+    pub fn public_key(&self) -> Result<PKey<Public>, ErrorStack> {
+        unsafe {
+            let key = cvt_p(ffi::X509_REQ_get_pubkey(self.as_ptr()))?;
+            Ok(PKey::from_ptr(key))
+        }
+    }
+
+    /// Returns the extensions of the certificate request.
+    ///
+    /// This corresponds to [`X509_REQ_get_extensions"]
+    pub fn extensions(&self) -> Result<Stack<X509Extension>, ErrorStack> {
+        unsafe {
+            let extensions = cvt_p(ffi::X509_REQ_get_extensions(self.as_ptr()))?;
+            Ok(Stack::from_ptr(extensions))
+        }
+    }
 }
 
 /// The result of peer certificate verification.
diff --git a/openssl/src/x509/tests.rs b/openssl/src/x509/tests.rs
index fa8056ad6..7ef4d1603 100644
--- a/openssl/src/x509/tests.rs
+++ b/openssl/src/x509/tests.rs
@@ -234,6 +234,10 @@ fn x509_req_builder() {
     builder.add_extensions(&extensions).unwrap();
 
     builder.sign(&pkey, MessageDigest::sha256()).unwrap();
+
+    let req = builder.build();
+    assert!(req.public_key().unwrap().public_eq(&pkey));
+    assert_eq!(req.extensions().unwrap().len(), extensions.len());
 }
 
 #[test]
-- 
GitLab