@@ -23,6 +23,13 @@ use crate::private::UnsafeFrom;
23
23
use crate :: rng:: Random ;
24
24
use crate :: hash:: Type as MdType ;
25
25
26
+ #[ derive( Debug , Copy , Clone , Eq , PartialEq ) ]
27
+ pub enum CertificateVersion {
28
+ V1 ,
29
+ V2 ,
30
+ V3
31
+ }
32
+
26
33
define ! (
27
34
#[ c_ty( x509_crt) ]
28
35
struct Certificate ;
@@ -114,6 +121,24 @@ pub struct LinkedCertificate {
114
121
inner : x509_crt ,
115
122
}
116
123
124
+ fn x509_buf_to_vec ( buf : & x509_buf ) -> Vec < u8 > {
125
+ if buf. p == core:: ptr:: null_mut ( ) || buf. len == 0 {
126
+ return vec ! [ ] ;
127
+ }
128
+
129
+ let slice = unsafe { core:: slice:: from_raw_parts ( buf. p , buf. len ) } ;
130
+ slice. to_owned ( )
131
+ }
132
+
133
+ fn x509_time_to_time ( tm : & x509_time ) -> Result < super :: Time > {
134
+ // ensure casts don't underflow
135
+ if tm. year < 0 || tm. mon < 0 || tm. day < 0 || tm. hour < 0 || tm. min < 0 || tm. sec < 0 {
136
+ return Err ( Error :: X509InvalidDate ) ;
137
+ }
138
+
139
+ super :: Time :: new ( tm. year as u16 , tm. mon as u8 , tm. day as u8 , tm. hour as u8 , tm. min as u8 , tm. sec as u8 ) . ok_or ( Error :: X509InvalidDate )
140
+ }
141
+
117
142
impl LinkedCertificate {
118
143
pub fn check_key_usage ( & self , usage : super :: KeyUsage ) -> bool {
119
144
unsafe { x509_crt_check_key_usage ( & self . inner , usage. bits ( ) ) }
@@ -136,10 +161,7 @@ impl LinkedCertificate {
136
161
}
137
162
138
163
pub fn issuer_raw ( & self ) -> Result < Vec < u8 > > {
139
- crate :: private:: alloc_vec_repeat (
140
- |buf, size| unsafe { x509_dn_gets ( buf as _ , size, & self . inner . issuer ) } ,
141
- false ,
142
- )
164
+ Ok ( x509_buf_to_vec ( & self . inner . issuer_raw ) )
143
165
}
144
166
145
167
pub fn subject ( & self ) -> Result < String > {
@@ -149,10 +171,7 @@ impl LinkedCertificate {
149
171
}
150
172
151
173
pub fn subject_raw ( & self ) -> Result < Vec < u8 > > {
152
- crate :: private:: alloc_vec_repeat (
153
- |buf, size| unsafe { x509_dn_gets ( buf as _ , size, & self . inner . subject ) } ,
154
- false ,
155
- )
174
+ Ok ( x509_buf_to_vec ( & self . inner . subject_raw ) )
156
175
}
157
176
158
177
pub fn serial ( & self ) -> Result < String > {
@@ -162,10 +181,7 @@ impl LinkedCertificate {
162
181
}
163
182
164
183
pub fn serial_raw ( & self ) -> Result < Vec < u8 > > {
165
- crate :: private:: alloc_vec_repeat (
166
- |buf, size| unsafe { x509_serial_gets ( buf as _ , size, & self . inner . serial ) } ,
167
- false ,
168
- )
184
+ Ok ( x509_buf_to_vec ( & self . inner . serial ) )
169
185
}
170
186
171
187
pub fn public_key ( & self ) -> & Pk {
@@ -180,6 +196,31 @@ impl LinkedCertificate {
180
196
unsafe { :: core:: slice:: from_raw_parts ( self . inner . raw . p , self . inner . raw . len ) }
181
197
}
182
198
199
+ pub fn version ( & self ) -> Result < CertificateVersion > {
200
+ match self . inner . version {
201
+ 1 => Ok ( CertificateVersion :: V1 ) ,
202
+ 2 => Ok ( CertificateVersion :: V2 ) ,
203
+ 3 => Ok ( CertificateVersion :: V3 ) ,
204
+ _ => Err ( Error :: X509InvalidVersion )
205
+ }
206
+ }
207
+
208
+ pub fn not_before ( & self ) -> Result < super :: Time > {
209
+ x509_time_to_time ( & self . inner . valid_from )
210
+ }
211
+
212
+ pub fn not_after ( & self ) -> Result < super :: Time > {
213
+ x509_time_to_time ( & self . inner . valid_to )
214
+ }
215
+
216
+ pub fn extensions_raw ( & self ) -> Result < Vec < u8 > > {
217
+ Ok ( x509_buf_to_vec ( & self . inner . v3_ext ) )
218
+ }
219
+
220
+ pub fn signature ( & self ) -> Result < Vec < u8 > > {
221
+ Ok ( x509_buf_to_vec ( & self . inner . sig ) )
222
+ }
223
+
183
224
pub fn digest_type ( & self ) -> MdType {
184
225
MdType :: from ( self . inner . sig_md )
185
226
}
@@ -722,7 +763,7 @@ JS7pkcufTIoN0Yj0SxAWLW711FgB
722
763
}
723
764
724
765
#[ test]
725
- fn channel_binding_hash ( ) {
766
+ fn cert_field_access ( ) {
726
767
const TEST_CERT_PEM : & ' static str = "-----BEGIN CERTIFICATE-----
727
768
MIIDLDCCAhSgAwIBAgIRALY0SS5pY9Yb/aIHvSAvmOswDQYJKoZIhvcNAQELBQAw
728
769
HzEQMA4GA1UEAxMHVGVzdCBDQTELMAkGA1UEBhMCVVMwHhcNMTkwMTA4MDAxODM1
@@ -745,6 +786,7 @@ cYp0bH/RcPTC0Z+ZaqSWMtfxRrk63MJQF9EXpDCdvQRcTMD9D85DJrMKn8aumq0M
745
786
746
787
let cert = Certificate :: from_pem ( & TEST_CERT_PEM . as_bytes ( ) ) . unwrap ( ) ;
747
788
789
+ assert_eq ! ( cert. version( ) . unwrap( ) , CertificateVersion :: V3 ) ;
748
790
assert_eq ! ( cert. issuer( ) . unwrap( ) , "CN=Test CA, C=US" ) ;
749
791
assert_eq ! ( cert. subject( ) . unwrap( ) , "CN=Test Cert, O=Test" ) ;
750
792
assert_eq ! (
@@ -753,6 +795,41 @@ cYp0bH/RcPTC0Z+ZaqSWMtfxRrk63MJQF9EXpDCdvQRcTMD9D85DJrMKn8aumq0M
753
795
) ;
754
796
assert_eq ! ( cert. digest_type( ) , MdType :: Sha256 ) ;
755
797
798
+ assert_eq ! ( hex:: encode( cert. serial_raw( ) . unwrap( ) ) , "00b634492e6963d61bfda207bd202f98eb" ) ;
799
+ assert_eq ! ( hex:: encode( cert. issuer_raw( ) . unwrap( ) ) , "301f3110300e0603550403130754657374204341310b3009060355040613025553" ) ;
800
+ assert_eq ! ( hex:: encode( cert. subject_raw( ) . unwrap( ) ) , "30233112301006035504031309546573742043657274310d300b060355040a130454657374" ) ;
801
+ assert_eq ! ( hex:: encode( cert. signature( ) . unwrap( ) ) , "4a4b2638e636a0c0121b0334e04b342ac17b178b1a3000d5dc84c0612941519e3ac99da72823809e643f9d1c0ff7ca2734c63974215879f6286532d43b0da6086fb212a96c8f573de4230c9ab3ae09d621719d2e35b3e91963d5e763a273f0e25d6bbc5fcd0cd7ace688821df1724fb3956c96046cd58126f3ae2a66680cccc8aaecbe680fa5fc79684ef33f64153b319713f42ea17aa3fdb99b94d95466ed75e572789d2c7388a49d35a6590429fe9b6959896e8658aee276f3474ff315051e6633be236d2acf552164ea6936122f9d718a746c7fd170f4c2d19f996aa49632d7f146b93adcc25017d117a4309dbd045c4cc0fd0fce4326b30a9fc6ae9aad0c" ) ;
802
+ assert_eq ! ( hex:: encode( cert. extensions_raw( ) . unwrap( ) ) , "30819f30210603551d0e041a04186839fad57e6544121cc6bc421953cc9620655c57cfac060230320603551d11042b302981117465737440666f7274616e69782e636f6d82146578616d706c652e666f7274616e69782e636f6d300c0603551d130101ff0402300030230603551d23041c301a801879076bcc8da0077e4116f84b8e4c9c5c6af7ec4fa000d98730130603551d25040c300a06082b06010505070302" ) ;
803
+
804
+ use crate :: x509:: Time ;
805
+ assert_eq ! ( cert. not_before( ) . unwrap( ) , Time :: new( 2019 , 1 , 8 , 0 , 18 , 35 ) . unwrap( ) ) ;
806
+ assert_eq ! ( cert. not_after( ) . unwrap( ) , Time :: new( 2029 , 1 , 5 , 0 , 18 , 35 ) . unwrap( ) ) ;
807
+ }
808
+
809
+ #[ test]
810
+ fn channel_binding_hash ( ) {
811
+ const TEST_CERT_PEM : & ' static str = "-----BEGIN CERTIFICATE-----
812
+ MIIDLDCCAhSgAwIBAgIRALY0SS5pY9Yb/aIHvSAvmOswDQYJKoZIhvcNAQELBQAw
813
+ HzEQMA4GA1UEAxMHVGVzdCBDQTELMAkGA1UEBhMCVVMwHhcNMTkwMTA4MDAxODM1
814
+ WhcNMjkwMTA1MDAxODM1WjAjMRIwEAYDVQQDEwlUZXN0IENlcnQxDTALBgNVBAoT
815
+ BFRlc3Qwgd8wDQYJKoZIhvcNAQEBBQADgc0AMIHJAoHBAKYINzSAKG1/Kn/5dWXq
816
+ cfJgfQkzVn1HPzdb4NNZL+H7woGuzDGrcQ7EPi7r4EuAEE2fCjhSfiYlacoBOxd/
817
+ k9Fp4Iv2ygCY1nj8RY0tFCZcZDVYj5F7uqyJMf7+QSOpnZ4cb3zdj1HkBmq7ac0C
818
+ 7tXkubvM6gBS3H3XlhfszcEjvhavaxVVoitdqW8RJ2DHvqGwFUxPgFCuuQudeCI/
819
+ UzBiPMRqu3Pr9Xhcc0ruG5SkCg5isbWWnKNj7X1gTre6WwIDAQABo4GiMIGfMCEG
820
+ A1UdDgQaBBhoOfrVfmVEEhzGvEIZU8yWIGVcV8+sBgIwMgYDVR0RBCswKYERdGVz
821
+ dEBmb3J0YW5peC5jb22CFGV4YW1wbGUuZm9ydGFuaXguY29tMAwGA1UdEwEB/wQC
822
+ MAAwIwYDVR0jBBwwGoAYeQdrzI2gB35BFvhLjkycXGr37E+gANmHMBMGA1UdJQQM
823
+ MAoGCCsGAQUFBwMCMA0GCSqGSIb3DQEBCwUAA4IBAQBKSyY45jagwBIbAzTgSzQq
824
+ wXsXixowANXchMBhKUFRnjrJnacoI4CeZD+dHA/3yic0xjl0IVh59ihlMtQ7DaYI
825
+ b7ISqWyPVz3kIwyas64J1iFxnS41s+kZY9XnY6Jz8OJda7xfzQzXrOaIgh3xck+z
826
+ lWyWBGzVgSbzripmaAzMyKrsvmgPpfx5aE7zP2QVOzGXE/QuoXqj/bmblNlUZu11
827
+ 5XJ4nSxziKSdNaZZBCn+m2lZiW6GWK7idvNHT/MVBR5mM74jbSrPVSFk6mk2Ei+d
828
+ cYp0bH/RcPTC0Z+ZaqSWMtfxRrk63MJQF9EXpDCdvQRcTMD9D85DJrMKn8aumq0M
829
+ -----END CERTIFICATE-----\0 " ;
830
+
831
+ let cert = Certificate :: from_pem ( & TEST_CERT_PEM . as_bytes ( ) ) . unwrap ( ) ;
832
+
756
833
let pk = cert. public_key ( ) ;
757
834
758
835
assert_eq ! ( pk. pk_type( ) , crate :: pk:: Type :: Rsa ) ;
0 commit comments