@@ -4,16 +4,31 @@ use libc::c_int;
4
4
use std:: mem;
5
5
use std:: ptr;
6
6
7
+ use crate :: asn1:: Asn1ObjectRef ;
7
8
use crate :: bio:: { MemBio , MemBioSlice } ;
8
9
use crate :: error:: ErrorStack ;
10
+ use crate :: nid:: Nid ;
9
11
use crate :: pkey:: { HasPrivate , PKeyRef } ;
10
- use crate :: stack:: { Stack , StackRef } ;
12
+ use crate :: stack:: { Stack , StackRef , Stackable } ;
11
13
use crate :: symm:: Cipher ;
14
+ use crate :: util:: ForeignTypeRefExt ;
12
15
use crate :: x509:: store:: X509StoreRef ;
13
16
use crate :: x509:: { X509Ref , X509 } ;
14
17
use crate :: { cvt, cvt_p} ;
15
18
use openssl_macros:: corresponds;
16
19
20
+ foreign_type_and_impl_send_sync ! {
21
+ type CType = ffi:: PKCS7_SIGNER_INFO ;
22
+ fn drop = ffi:: PKCS7_SIGNER_INFO_free ;
23
+
24
+ pub struct Pkcs7SignerInfo ;
25
+ pub struct Pkcs7SignerInfoRef ;
26
+ }
27
+
28
+ impl Stackable for Pkcs7SignerInfo {
29
+ type StackType = ffi:: stack_st_PKCS7_SIGNER_INFO ;
30
+ }
31
+
17
32
foreign_type_and_impl_send_sync ! {
18
33
type CType = ffi:: PKCS7 ;
19
34
fn drop = ffi:: PKCS7_free ;
@@ -27,6 +42,19 @@ foreign_type_and_impl_send_sync! {
27
42
pub struct Pkcs7Ref ;
28
43
}
29
44
45
+ foreign_type_and_impl_send_sync ! {
46
+ type CType = ffi:: PKCS7_SIGNED ;
47
+ fn drop = ffi:: PKCS7_SIGNED_free ;
48
+
49
+ /// A PKCS#7 signed data structure.
50
+ ///
51
+ /// Contains signed data.
52
+ pub struct Pkcs7Signed ;
53
+
54
+ /// Reference to `Pkcs7Signed`
55
+ pub struct Pkcs7SignedRef ;
56
+ }
57
+
30
58
bitflags ! {
31
59
#[ derive( Copy , Clone , Debug , Eq , Hash , Ord , PartialEq , PartialOrd ) ]
32
60
#[ repr( transparent) ]
@@ -281,11 +309,43 @@ impl Pkcs7Ref {
281
309
Ok ( stack)
282
310
}
283
311
}
312
+
313
+ /// Return the type of a PKCS#7 structure as an Asn1Object
314
+ pub fn type_ ( & self ) -> Option < & Asn1ObjectRef > {
315
+ unsafe {
316
+ let ptr = ( * self . as_ptr ( ) ) . type_ ;
317
+ Asn1ObjectRef :: from_const_ptr_opt ( ptr)
318
+ }
319
+ }
320
+
321
+ /// Get the signed data of a PKCS#7 structure of type PKCS7_SIGNED
322
+ pub fn signed ( & self ) -> Option < & Pkcs7SignedRef > {
323
+ unsafe {
324
+ if self . type_ ( ) . map ( |x| x. nid ( ) ) != Some ( Nid :: PKCS7_SIGNED ) {
325
+ return None ;
326
+ }
327
+ let signed_data = ( * self . as_ptr ( ) ) . d . sign ;
328
+ Pkcs7SignedRef :: from_const_ptr_opt ( signed_data)
329
+ }
330
+ }
331
+ }
332
+
333
+ impl Pkcs7SignedRef {
334
+ /// Get the stack of certificates from the PKCS7_SIGNED object
335
+ pub fn certificates ( & self ) -> Option < & StackRef < X509 > > {
336
+ unsafe {
337
+ self . as_ptr ( )
338
+ . as_ref ( )
339
+ . and_then ( |x| x. cert . as_mut ( ) )
340
+ . and_then ( |x| StackRef :: < X509 > :: from_const_ptr_opt ( x) )
341
+ }
342
+ }
284
343
}
285
344
286
345
#[ cfg( test) ]
287
346
mod tests {
288
347
use crate :: hash:: MessageDigest ;
348
+ use crate :: nid:: Nid ;
289
349
use crate :: pkcs7:: { Pkcs7 , Pkcs7Flags } ;
290
350
use crate :: pkey:: PKey ;
291
351
use crate :: stack:: Stack ;
@@ -307,6 +367,10 @@ mod tests {
307
367
308
368
let pkcs7 =
309
369
Pkcs7 :: encrypt ( & certs, message. as_bytes ( ) , cipher, flags) . expect ( "should succeed" ) ;
370
+ assert_eq ! (
371
+ pkcs7. type_( ) . expect( "PKCS7 should have a type" ) . nid( ) ,
372
+ Nid :: PKCS7_ENVELOPED
373
+ ) ;
310
374
311
375
let encrypted = pkcs7
312
376
. to_smime ( message. as_bytes ( ) , flags)
@@ -340,6 +404,10 @@ mod tests {
340
404
341
405
let pkcs7 =
342
406
Pkcs7 :: sign ( & cert, & pkey, & certs, message. as_bytes ( ) , flags) . expect ( "should succeed" ) ;
407
+ assert_eq ! (
408
+ pkcs7. type_( ) . expect( "PKCS7 should have a type" ) . nid( ) ,
409
+ Nid :: PKCS7_SIGNED
410
+ ) ;
343
411
344
412
let signed = pkcs7
345
413
. to_smime ( message. as_bytes ( ) , flags)
@@ -384,6 +452,10 @@ mod tests {
384
452
385
453
let pkcs7 =
386
454
Pkcs7 :: sign ( & cert, & pkey, & certs, message. as_bytes ( ) , flags) . expect ( "should succeed" ) ;
455
+ assert_eq ! (
456
+ pkcs7. type_( ) . expect( "PKCS7 should have a type" ) . nid( ) ,
457
+ Nid :: PKCS7_SIGNED
458
+ ) ;
387
459
388
460
let signed = pkcs7
389
461
. to_smime ( message. as_bytes ( ) , flags)
@@ -421,6 +493,10 @@ mod tests {
421
493
422
494
let pkcs7 =
423
495
Pkcs7 :: sign ( & cert, & pkey, & certs, message. as_bytes ( ) , flags) . expect ( "should succeed" ) ;
496
+ assert_eq ! (
497
+ pkcs7. type_( ) . expect( "PKCS7 should have a type" ) . nid( ) ,
498
+ Nid :: PKCS7_SIGNED
499
+ ) ;
424
500
425
501
let signed = pkcs7
426
502
. to_smime ( message. as_bytes ( ) , flags)
@@ -445,4 +521,53 @@ mod tests {
445
521
446
522
assert ! ( result. is_err( ) ) ;
447
523
}
524
+
525
+ #[ test]
526
+ fn signed_data_certificates ( ) {
527
+ let cert = include_bytes ! ( "../test/cert.pem" ) ;
528
+ let cert = X509 :: from_pem ( cert) . unwrap ( ) ;
529
+ let mut extra_certs = Stack :: < X509 > :: new ( ) . unwrap ( ) ;
530
+ for cert in
531
+ X509 :: stack_from_pem ( include_bytes ! ( "../test/certs.pem" ) ) . expect ( "should succeed" )
532
+ {
533
+ extra_certs. push ( cert) . expect ( "should succeed" ) ;
534
+ }
535
+
536
+ let message = "foo" ;
537
+ let flags = Pkcs7Flags :: STREAM ;
538
+ let pkey = include_bytes ! ( "../test/key.pem" ) ;
539
+ let pkey = PKey :: private_key_from_pem ( pkey) . unwrap ( ) ;
540
+
541
+ let pkcs7 = Pkcs7 :: sign ( & cert, & pkey, & extra_certs, message. as_bytes ( ) , flags)
542
+ . expect ( "should succeed" ) ;
543
+ assert_eq ! (
544
+ pkcs7. type_( ) . expect( "PKCS7 should have a type" ) . nid( ) ,
545
+ Nid :: PKCS7_SIGNED
546
+ ) ;
547
+ let signed_data_certs = pkcs7. signed ( ) . and_then ( |x| x. certificates ( ) ) ;
548
+ assert_eq ! ( signed_data_certs. expect( "should succeed" ) . len( ) , 3 ) ;
549
+ }
550
+
551
+ #[ test]
552
+ fn signed_data_certificates_no_signed_data ( ) {
553
+ let cert = include_bytes ! ( "../test/certs.pem" ) ;
554
+ let cert = X509 :: from_pem ( cert) . unwrap ( ) ;
555
+ let mut certs = Stack :: new ( ) . unwrap ( ) ;
556
+ certs. push ( cert) . unwrap ( ) ;
557
+ let message: String = String :: from ( "foo" ) ;
558
+ let cipher = Cipher :: des_ede3_cbc ( ) ;
559
+ let flags = Pkcs7Flags :: STREAM ;
560
+
561
+ // Use `Pkcs7::encrypt` since it populates the PKCS7_ENVELOPE struct rather than
562
+ // PKCS7_SIGNED
563
+ let pkcs7 =
564
+ Pkcs7 :: encrypt ( & certs, message. as_bytes ( ) , cipher, flags) . expect ( "should succeed" ) ;
565
+ assert_eq ! (
566
+ pkcs7. type_( ) . expect( "PKCS7 should have a type" ) . nid( ) ,
567
+ Nid :: PKCS7_ENVELOPED
568
+ ) ;
569
+
570
+ let signed_data_certs = pkcs7. signed ( ) . and_then ( |x| x. certificates ( ) ) ;
571
+ assert ! ( signed_data_certs. is_none( ) )
572
+ }
448
573
}
0 commit comments