diff options
| author | Steven Fackler <[email protected]> | 2017-02-11 08:34:45 -0800 |
|---|---|---|
| committer | GitHub <[email protected]> | 2017-02-11 08:34:45 -0800 |
| commit | ad07b19ed34a2fbea76964df53870799352fd237 (patch) | |
| tree | d5fd069f824ab5655e319c615cb4207ca19a5c1e /openssl/src | |
| parent | Merge pull request #574 from stephanbuys/macos_readme (diff) | |
| parent | X509 signature algorithm access (diff) | |
| download | rust-openssl-ad07b19ed34a2fbea76964df53870799352fd237.tar.xz rust-openssl-ad07b19ed34a2fbea76964df53870799352fd237.zip | |
Merge pull request #579 from sfackler/x509-signature
X509 signature access
Diffstat (limited to 'openssl/src')
| -rw-r--r-- | openssl/src/asn1.rs | 52 | ||||
| -rw-r--r-- | openssl/src/x509/mod.rs | 79 | ||||
| -rw-r--r-- | openssl/src/x509/tests.rs | 18 |
3 files changed, 136 insertions, 13 deletions
diff --git a/openssl/src/asn1.rs b/openssl/src/asn1.rs index fd932723..2c38e14d 100644 --- a/openssl/src/asn1.rs +++ b/openssl/src/asn1.rs @@ -1,6 +1,6 @@ use ffi; use foreign_types::{ForeignType, ForeignTypeRef}; -use libc::{c_long, c_char}; +use libc::{c_long, c_char, c_int}; use std::fmt; use std::ptr; use std::slice; @@ -9,6 +9,7 @@ use std::str; use {cvt, cvt_p}; use bio::MemBio; use error::ErrorStack; +use nid::Nid; use string::OpensslString; foreign_type! { @@ -93,6 +94,55 @@ impl Asn1StringRef { } } +foreign_type! { + type CType = ffi::ASN1_BIT_STRING; + fn drop = ffi::ASN1_BIT_STRING_free; + + pub struct Asn1BitString; + pub struct Asn1BitStringRef; +} + +impl Asn1BitStringRef { + pub fn as_slice(&self) -> &[u8] { + unsafe { slice::from_raw_parts(ASN1_STRING_data(self.as_ptr() as *mut _), self.len()) } + } + + pub fn len(&self) -> usize { + unsafe { ffi::ASN1_STRING_length(self.as_ptr() as *mut _) as usize } + } +} + +foreign_type! { + type CType = ffi::ASN1_OBJECT; + fn drop = ffi::ASN1_OBJECT_free; + + pub struct Asn1Object; + pub struct Asn1ObjectRef; +} + +impl Asn1ObjectRef { + /// Returns the NID associated with this OID. + pub fn nid(&self) -> Nid { + unsafe { + Nid::from_raw(ffi::OBJ_obj2nid(self.as_ptr())) + } + } +} + +impl fmt::Display for Asn1ObjectRef { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + unsafe { + let mut buf = [0; 80]; + let len = ffi::OBJ_obj2txt(buf.as_mut_ptr() as *mut _, + buf.len() as c_int, + self.as_ptr(), + 0); + let s = try!(str::from_utf8(&buf[..len as usize]).map_err(|_| fmt::Error)); + fmt.write_str(s) + } + } +} + #[cfg(any(ossl101, ossl102))] use ffi::ASN1_STRING_data; diff --git a/openssl/src/x509/mod.rs b/openssl/src/x509/mod.rs index a0b76fef..de7aece7 100644 --- a/openssl/src/x509/mod.rs +++ b/openssl/src/x509/mod.rs @@ -13,7 +13,7 @@ use std::slice; use std::str; use {cvt, cvt_p}; -use asn1::{Asn1StringRef, Asn1Time, Asn1TimeRef}; +use asn1::{Asn1StringRef, Asn1Time, Asn1TimeRef, Asn1BitStringRef, Asn1ObjectRef}; use bio::MemBioSlice; use hash::MessageDigest; use pkey::{PKey, PKeyRef}; @@ -410,8 +410,8 @@ impl X509Ref { } } - /// Returns certificate Not After validity period. - pub fn not_after<'a>(&'a self) -> &'a Asn1TimeRef { + /// Returns the certificate's Not After validity period. + pub fn not_after(&self) -> &Asn1TimeRef { unsafe { let date = compat::X509_get_notAfter(self.as_ptr()); assert!(!date.is_null()); @@ -419,8 +419,8 @@ impl X509Ref { } } - /// Returns certificate Not Before validity period. - pub fn not_before<'a>(&'a self) -> &'a Asn1TimeRef { + /// Returns the certificate's Not Before validity period. + pub fn not_before(&self) -> &Asn1TimeRef { unsafe { let date = compat::X509_get_notBefore(self.as_ptr()); assert!(!date.is_null()); @@ -428,6 +428,26 @@ impl X509Ref { } } + /// Returns the certificate's signature + pub fn signature(&self) -> &Asn1BitStringRef { + unsafe { + let mut signature = ptr::null(); + compat::X509_get0_signature(&mut signature, ptr::null_mut(), self.as_ptr()); + assert!(!signature.is_null()); + Asn1BitStringRef::from_ptr(signature as *mut _) + } + } + + /// Returns the certificate's signature algorithm. + pub fn signature_algorithm(&self) -> &X509AlgorithmRef { + unsafe { + let mut algor = ptr::null(); + compat::X509_get0_signature(ptr::null_mut(), &mut algor, self.as_ptr()); + assert!(!algor.is_null()); + X509AlgorithmRef::from_ptr(algor as *mut _) + } + } + /// Returns the list of OCSP responder URLs specified in the certificate's Authority Information /// Access field. pub fn ocsp_responders(&self) -> Result<Stack<OpensslString>, ErrorStack> { @@ -800,12 +820,23 @@ impl Stackable for GeneralName { type StackType = ffi::stack_st_GENERAL_NAME; } -#[test] -fn test_negative_serial() { - // I guess that's enough to get a random negative number - for _ in 0..1000 { - assert!(X509Generator::random_serial().unwrap() > 0, - "All serials should be positive"); +foreign_type! { + type CType = ffi::X509_ALGOR; + fn drop = ffi::X509_ALGOR_free; + + pub struct X509Algorithm; + pub struct X509AlgorithmRef; +} + +impl X509AlgorithmRef { + /// Returns the ASN.1 OID of this algorithm. + pub fn object(&self) -> &Asn1ObjectRef { + unsafe { + let mut oid = ptr::null(); + compat::X509_ALGOR_get0(&mut oid, ptr::null_mut(), ptr::null_mut(), self.as_ptr()); + assert!(!oid.is_null()); + Asn1ObjectRef::from_ptr(oid as *mut _) + } } } @@ -815,12 +846,14 @@ mod compat { pub use ffi::X509_getm_notBefore as X509_get_notBefore; pub use ffi::X509_up_ref; pub use ffi::X509_get0_extensions; + pub use ffi::X509_get0_signature; + pub use ffi::X509_ALGOR_get0; } #[cfg(ossl10x)] #[allow(bad_style)] mod compat { - use libc::c_int; + use libc::{c_int, c_void}; use ffi; pub unsafe fn X509_get_notAfter(x: *mut ffi::X509) -> *mut ffi::ASN1_TIME { @@ -848,4 +881,26 @@ mod compat { (*info).extensions } } + + pub unsafe fn X509_get0_signature(psig: *mut *const ffi::ASN1_BIT_STRING, + palg: *mut *const ffi::X509_ALGOR, + x: *const ffi::X509) { + if !psig.is_null() { + *psig = (*x).signature; + } + if !palg.is_null() { + *palg = (*x).sig_alg; + } + } + + pub unsafe fn X509_ALGOR_get0(paobj: *mut *const ffi::ASN1_OBJECT, + pptype: *mut c_int, + pval: *mut *mut c_void, + alg: *const ffi::X509_ALGOR) { + if !paobj.is_null() { + *paobj = (*alg).algorithm; + } + assert!(pptype.is_null()); + assert!(pval.is_null()); + } } diff --git a/openssl/src/x509/tests.rs b/openssl/src/x509/tests.rs index 01cbf2ec..d6ec7beb 100644 --- a/openssl/src/x509/tests.rs +++ b/openssl/src/x509/tests.rs @@ -220,3 +220,21 @@ fn ecdsa_cert() { ctx.set_private_key(&key).unwrap(); ctx.check_private_key().unwrap(); } + +#[test] +fn signature() { + let cert = include_bytes!("../../test/cert.pem"); + let cert = X509::from_pem(cert).unwrap(); + let signature = cert.signature(); + assert_eq!(signature.as_slice().to_hex(), + "4af607b889790b43470442cfa551cdb8b6d0b0340d2958f76b9e3ef6ad4992230cead6842587f0ecad5\ + 78e6e11a221521e940187e3d6652de14e84e82f6671f097cc47932e022add3c0cb54a26bf27fa84c107\ + 4971caa6bee2e42d34a5b066c427f2d452038082b8073993399548088429de034fdd589dcfb0dd33be7\ + ebdfdf698a28d628a89568881d658151276bde333600969502c4e62e1d3470a683364dfb241f78d310a\ + 89c119297df093eb36b7fd7540224f488806780305d1e79ffc938fe2275441726522ab36d88348e6c51\ + f13dcc46b5e1cdac23c974fd5ef86aa41e91c9311655090a52333bc79687c748d833595d4c5f987508f\ + e121997410d37c"); + let algorithm = cert.signature_algorithm(); + assert_eq!(algorithm.object().nid(), nid::SHA256WITHRSAENCRYPTION); + assert_eq!(algorithm.object().to_string(), "sha256WithRSAEncryption"); +} |