From a1d7956f828a5208f16d49871b7c1965d21a6893 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Fri, 10 Feb 2017 19:38:51 -0800 Subject: Add Asn1BitString --- openssl/src/asn1.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'openssl/src') diff --git a/openssl/src/asn1.rs b/openssl/src/asn1.rs index fd932723..0ba54440 100644 --- a/openssl/src/asn1.rs +++ b/openssl/src/asn1.rs @@ -93,6 +93,24 @@ 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 } + } +} + #[cfg(any(ossl101, ossl102))] use ffi::ASN1_STRING_data; -- cgit v1.2.3 From 8e5735d84c43cfc2a18c1178893eedf9b8373e8e Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Fri, 10 Feb 2017 19:59:11 -0800 Subject: X509 signature access --- openssl/src/x509/mod.rs | 32 +++++++++++++++++++++++++++----- openssl/src/x509/tests.rs | 15 +++++++++++++++ 2 files changed, 42 insertions(+), 5 deletions(-) (limited to 'openssl/src') diff --git a/openssl/src/x509/mod.rs b/openssl/src/x509/mod.rs index a0b76fef..5829b8e4 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}; 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,16 @@ 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 list of OCSP responder URLs specified in the certificate's Authority Information /// Access field. pub fn ocsp_responders(&self) -> Result, ErrorStack> { @@ -815,6 +825,7 @@ 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; } #[cfg(ossl10x)] @@ -848,4 +859,15 @@ 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; + } + } } diff --git a/openssl/src/x509/tests.rs b/openssl/src/x509/tests.rs index 01cbf2ec..abd83ec1 100644 --- a/openssl/src/x509/tests.rs +++ b/openssl/src/x509/tests.rs @@ -220,3 +220,18 @@ 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"); +} -- cgit v1.2.3 From 03fe3015dc7f8ec321e483c3dde63766f1c365ad Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Fri, 10 Feb 2017 21:37:33 -0800 Subject: X509 signature algorithm access --- openssl/src/asn1.rs | 34 +++++++++++++++++++++++++++++++- openssl/src/x509/mod.rs | 49 +++++++++++++++++++++++++++++++++++++++-------- openssl/src/x509/tests.rs | 3 +++ 3 files changed, 77 insertions(+), 9 deletions(-) (limited to 'openssl/src') diff --git a/openssl/src/asn1.rs b/openssl/src/asn1.rs index 0ba54440..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! { @@ -111,6 +112,37 @@ impl Asn1BitStringRef { } } +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 5829b8e4..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, Asn1BitStringRef}; +use asn1::{Asn1StringRef, Asn1Time, Asn1TimeRef, Asn1BitStringRef, Asn1ObjectRef}; use bio::MemBioSlice; use hash::MessageDigest; use pkey::{PKey, PKeyRef}; @@ -438,6 +438,16 @@ impl X509Ref { } } + /// 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, ErrorStack> { @@ -810,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 _) + } } } @@ -826,12 +847,13 @@ mod compat { 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 { @@ -870,4 +892,15 @@ mod compat { *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 abd83ec1..d6ec7beb 100644 --- a/openssl/src/x509/tests.rs +++ b/openssl/src/x509/tests.rs @@ -234,4 +234,7 @@ fn signature() { 89c119297df093eb36b7fd7540224f488806780305d1e79ffc938fe2275441726522ab36d88348e6c51\ f13dcc46b5e1cdac23c974fd5ef86aa41e91c9311655090a52333bc79687c748d833595d4c5f987508f\ e121997410d37c"); + let algorithm = cert.signature_algorithm(); + assert_eq!(algorithm.object().nid(), nid::SHA256WITHRSAENCRYPTION); + assert_eq!(algorithm.object().to_string(), "sha256WithRSAEncryption"); } -- cgit v1.2.3