1
1
use ffi;
2
2
use foreign_types:: ForeignTypeRef ;
3
3
use libc:: { c_int, c_long, c_ulong} ;
4
+
5
+ use std:: error:: Error ;
6
+ use std:: fmt;
4
7
use std:: mem;
5
8
use std:: ptr;
6
9
@@ -28,6 +31,47 @@ bitflags! {
28
31
}
29
32
}
30
33
34
+ #[ derive( Debug ) ]
35
+ pub enum OcspNonceCheckSuccessResult {
36
+ PresentAndEqual , // 1
37
+ Absent , // 2
38
+ PresentInResponseOnly , // 3
39
+ }
40
+
41
+ impl fmt:: Display for OcspNonceCheckSuccessResult {
42
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
43
+ let message = match * self {
44
+ OcspNonceCheckSuccessResult :: PresentAndEqual => "Nonces Present and Equal" ,
45
+ OcspNonceCheckSuccessResult :: Absent => "Nonces Absent from Request and Response" ,
46
+ OcspNonceCheckSuccessResult :: PresentInResponseOnly => "Nonce Present in Response Only" ,
47
+ } ;
48
+ write ! ( f, "{}" , message)
49
+ }
50
+ }
51
+
52
+ #[ derive( Debug ) ]
53
+ pub enum OcspNonceCheckErrorResult {
54
+ PresentAndUnequal , // 0
55
+ PresentInRequestOnly , // -1
56
+ Unknown ( ErrorStack ) , // any other return value
57
+ }
58
+
59
+ impl fmt:: Display for OcspNonceCheckErrorResult {
60
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
61
+ match * self {
62
+ OcspNonceCheckErrorResult :: PresentAndUnequal => write ! ( f, "Nonces Present and Unequal!" ) ,
63
+ OcspNonceCheckErrorResult :: PresentInRequestOnly => write ! ( f, "Nonce Present in Request Only!" ) ,
64
+ OcspNonceCheckErrorResult :: Unknown ( ref err) => err. fmt ( f) ,
65
+ }
66
+ }
67
+ }
68
+
69
+ impl Error for OcspNonceCheckErrorResult {
70
+ fn description ( & self ) -> & str {
71
+ "an error in OCSP nonce checking"
72
+ }
73
+ }
74
+
31
75
#[ derive( Copy , Clone , Debug , PartialEq , Eq ) ]
32
76
pub struct OcspResponseStatus ( c_int ) ;
33
77
@@ -202,6 +246,24 @@ impl OcspBasicResponseRef {
202
246
}
203
247
}
204
248
}
249
+
250
+ pub fn add_nonce ( & mut self , val : Option < & [ u8 ] > ) -> Result < ( ) , ErrorStack > {
251
+ unsafe {
252
+ let ( ptr, len) = match val {
253
+ Some ( slice) => ( slice. as_ptr ( ) as * mut _ , slice. len ( ) as c_int ) ,
254
+ None => ( ptr:: null_mut ( ) , 0 ) ,
255
+ } ;
256
+ cvt ( ffi:: OCSP_basic_add1_nonce ( self . as_ptr ( ) , ptr, len) ) ?;
257
+ Ok ( ( ) )
258
+ }
259
+ }
260
+
261
+ pub fn copy_nonce ( & mut self , req : & OcspRequestRef ) -> Result < ( ) , ErrorStack > {
262
+ unsafe {
263
+ cvt ( ffi:: OCSP_copy_nonce ( self . as_ptr ( ) , req. as_ptr ( ) ) ) ?;
264
+ Ok ( ( ) )
265
+ }
266
+ }
205
267
}
206
268
207
269
foreign_type_and_impl_send_sync ! {
@@ -340,6 +402,17 @@ impl OcspRequestRef {
340
402
Ok ( OcspOneReqRef :: from_ptr_mut ( ptr) )
341
403
}
342
404
}
405
+
406
+ pub fn add_nonce ( & mut self , val : Option < & [ u8 ] > ) -> Result < ( ) , ErrorStack > {
407
+ unsafe {
408
+ let ( ptr, len) = match val {
409
+ Some ( slice) => ( slice. as_ptr ( ) as * mut _ , slice. len ( ) as c_int ) ,
410
+ None => ( ptr:: null_mut ( ) , 0 ) ,
411
+ } ;
412
+ cvt ( ffi:: OCSP_request_add1_nonce ( self . as_ptr ( ) , ptr, len) ) ?;
413
+ Ok ( ( ) )
414
+ }
415
+ }
343
416
}
344
417
345
418
foreign_type_and_impl_send_sync ! {
@@ -349,3 +422,56 @@ foreign_type_and_impl_send_sync! {
349
422
pub struct OcspOneReq ;
350
423
pub struct OcspOneReqRef ;
351
424
}
425
+
426
+ pub fn check_nonce ( req : & OcspRequestRef , bs : & OcspBasicResponseRef ) -> Result < OcspNonceCheckSuccessResult , OcspNonceCheckErrorResult > {
427
+ unsafe {
428
+ match ffi:: OCSP_check_nonce ( req. as_ptr ( ) , bs. as_ptr ( ) ) {
429
+ // good cases
430
+ 1 => Ok ( OcspNonceCheckSuccessResult :: PresentAndEqual ) ,
431
+ 2 => Ok ( OcspNonceCheckSuccessResult :: Absent ) ,
432
+ 3 => Ok ( OcspNonceCheckSuccessResult :: PresentInResponseOnly ) ,
433
+ // bad cases
434
+ 0 => Err ( OcspNonceCheckErrorResult :: PresentAndUnequal ) ,
435
+ -1 => Err ( OcspNonceCheckErrorResult :: PresentInRequestOnly ) ,
436
+ _ => Err ( OcspNonceCheckErrorResult :: Unknown ( ErrorStack :: get ( ) ) ) , //something else!
437
+ }
438
+ }
439
+ }
440
+
441
+ #[ cfg( test) ]
442
+ mod tests {
443
+ use hex:: FromHex ;
444
+
445
+ use super :: * ;
446
+ use hash:: MessageDigest ;
447
+ use x509:: X509 ;
448
+
449
+ #[ test]
450
+ fn test_create_ocsp_request ( ) {
451
+ let subject = include_bytes ! ( "../test/cert.pem" ) ;
452
+ let subject = X509 :: from_pem ( subject) . unwrap ( ) ;
453
+ let issuer = include_bytes ! ( "../test/root-ca.pem" ) ;
454
+ let issuer = X509 :: from_pem ( issuer) . unwrap ( ) ;
455
+
456
+ let req_der = include_bytes ! ( "../test/ocsp-req.der" ) ;
457
+ let req_nonce_der = include_bytes ! ( "../test/ocsp-req-nonce.der" ) ;
458
+
459
+ let cert_id = OcspCertId :: from_cert (
460
+ MessageDigest :: sha1 ( ) ,
461
+ & subject,
462
+ & issuer
463
+ ) . unwrap ( ) ;
464
+
465
+ let mut req = OcspRequest :: new ( ) . unwrap ( ) ;
466
+ req. add_id ( cert_id) . unwrap ( ) ;
467
+
468
+ assert_eq ! ( & * req. to_der( ) . unwrap( ) , req_der. as_ref( ) ) ;
469
+
470
+
471
+ let nonce = Vec :: from_hex ( "4413A2C5019A7C3A384CDD8AB30E3816" ) . unwrap ( ) ;
472
+ req. add_nonce ( Some ( & nonce) ) . unwrap ( ) ;
473
+
474
+ assert_eq ! ( & * req. to_der( ) . unwrap( ) , req_nonce_der. as_ref( ) ) ;
475
+ }
476
+
477
+ }
0 commit comments