@@ -430,35 +430,47 @@ impl rustls_certified_key {
430
430
}
431
431
}
432
432
433
- /// A root certificate store.
434
- /// <https://docs.rs/rustls/latest/rustls/struct.RootCertStore.html>
435
- pub struct rustls_root_cert_store {
433
+ /// A `rustls_root_cert_store` being constructed. A builder can be modified by,
434
+ /// adding trust anchor root certificates with `rustls_root_cert_store_builder_add_pem`.
435
+ /// Once you're done adding root certificates, call `rustls_root_cert_store_builder_build`
436
+ /// to turn it into a `rustls_root_cert_store`. This object is not safe
437
+ /// for concurrent mutation.
438
+ pub struct rustls_root_cert_store_builder {
436
439
// We use the opaque struct pattern to tell C about our types without
437
440
// telling them what's inside.
438
441
// https://doc.rust-lang.org/nomicon/ffi.html#representing-opaque-structs
439
442
_private : [ u8 ; 0 ] ,
440
443
}
441
444
442
- impl CastPtr for rustls_root_cert_store {
443
- type RustType = RootCertStore ;
445
+ pub ( crate ) struct RootCertStoreBuilder {
446
+ roots : RootCertStore ,
444
447
}
445
448
446
- impl ArcCastPtr for rustls_root_cert_store { }
449
+ impl CastPtr for rustls_root_cert_store_builder {
450
+ type RustType = Option < RootCertStoreBuilder > ;
451
+ }
447
452
448
- impl rustls_root_cert_store {
449
- /// Create a rustls_root_cert_store. Caller owns the memory and must
450
- /// eventually call rustls_root_cert_store_free. The store starts out empty.
451
- /// Caller must add root certificates with rustls_root_cert_store_add_pem.
452
- /// <https://docs.rs/rustls/latest/rustls/struct.RootCertStore.html#method.empty>
453
+ impl BoxCastPtr for rustls_root_cert_store_builder { }
454
+
455
+ impl rustls_root_cert_store_builder {
456
+ /// Create a `rustls_root_cert_store_builder`. Caller owns the memory and must
457
+ /// eventually call `rustls_root_cert_store_builder_build`, then free the
458
+ /// resulting `rustls_root_cert_store`.
459
+ ///
460
+ /// If you wish to abandon the builder without calling `rustls_root_cert_store_builder_build`,
461
+ /// it must be freed with `rustls_root_cert_store_builder_free`.
453
462
#[ no_mangle]
454
- pub extern "C" fn rustls_root_cert_store_new ( ) -> * const rustls_root_cert_store {
463
+ pub extern "C" fn rustls_root_cert_store_builder_new ( ) -> * mut rustls_root_cert_store_builder {
455
464
ffi_panic_boundary ! {
456
- let store = rustls:: RootCertStore :: empty( ) ;
457
- ArcCastPtr :: to_const_ptr( store)
465
+ let builder = RootCertStoreBuilder {
466
+ roots: RootCertStore :: empty( ) ,
467
+ } ;
468
+ BoxCastPtr :: to_mut_ptr( Some ( builder) )
458
469
}
459
470
}
460
471
461
- /// Add one or more certificates to the root cert store using PEM encoded data.
472
+ /// Add one or more certificates to the root cert store builder using PEM
473
+ /// encoded data.
462
474
///
463
475
/// When `strict` is true an error will return a `CertificateParseError`
464
476
/// result. So will an attempt to parse data that has zero certificates.
@@ -467,15 +479,19 @@ impl rustls_root_cert_store {
467
479
/// This may be useful on systems that have syntactically invalid root
468
480
/// certificates.
469
481
#[ no_mangle]
470
- pub extern "C" fn rustls_root_cert_store_add_pem (
471
- store : * mut rustls_root_cert_store ,
482
+ pub extern "C" fn rustls_root_cert_store_builder_add_pem (
483
+ builder : * mut rustls_root_cert_store_builder ,
472
484
pem : * const u8 ,
473
485
pem_len : size_t ,
474
486
strict : bool ,
475
487
) -> rustls_result {
476
488
ffi_panic_boundary ! {
477
489
let certs_pem: & [ u8 ] = try_slice!( pem, pem_len) ;
478
- let store: & mut RootCertStore = try_mut_from_ptr!( store) ;
490
+ let builder: & mut Option <RootCertStoreBuilder > = try_mut_from_ptr!( builder) ;
491
+ let builder = match builder {
492
+ None => return AlreadyUsed ,
493
+ Some ( b) => b,
494
+ } ;
479
495
480
496
let certs_der: Result <Vec <CertificateDer >, _> = rustls_pemfile:: certs( & mut Cursor :: new( certs_pem) ) . collect( ) ;
481
497
let certs_der = match certs_der {
@@ -491,11 +507,68 @@ impl rustls_root_cert_store {
491
507
return rustls_result:: CertificateParseError ;
492
508
}
493
509
494
- store. roots. append( & mut new_store. roots) ;
510
+ builder. roots. roots. append( & mut new_store. roots) ;
511
+
495
512
rustls_result:: Ok
496
513
}
497
514
}
498
515
516
+ /// Create a new `rustls_root_cert_store` from the builder.
517
+ ///
518
+ /// The builder is consumed and cannot be used again, but must still be freed.
519
+ ///
520
+ /// The root cert store can be used in several `rustls_web_pki_client_cert_verifier_builder_new`
521
+ /// instances and must be freed by the application when no longer needed. See the documentation of
522
+ /// `rustls_root_cert_store_free` for details about lifetime.
523
+ #[ no_mangle]
524
+ pub extern "C" fn rustls_root_cert_store_builder_build (
525
+ builder : * mut rustls_root_cert_store_builder ,
526
+ root_cert_store_out : * mut * const rustls_root_cert_store ,
527
+ ) -> rustls_result {
528
+ ffi_panic_boundary ! {
529
+ let builder: & mut Option <RootCertStoreBuilder > = try_mut_from_ptr!( builder) ;
530
+ let builder = match builder {
531
+ None => return AlreadyUsed ,
532
+ Some ( b) => b,
533
+ } ;
534
+
535
+ unsafe {
536
+ * root_cert_store_out = ArcCastPtr :: to_const_ptr( builder. roots. clone( ) ) ;
537
+ }
538
+
539
+ rustls_result:: Ok
540
+ }
541
+ }
542
+
543
+ /// Free a `rustls_root_cert_store_builder` previously returned from
544
+ /// `rustls_root_cert_store_builder_new`. Calling with NULL is fine. Must not be
545
+ /// called twice with the same value.
546
+ #[ no_mangle]
547
+ pub extern "C" fn rustls_root_cert_store_builder_free (
548
+ builder : * mut rustls_root_cert_store_builder ,
549
+ ) {
550
+ ffi_panic_boundary ! {
551
+ BoxCastPtr :: to_box( builder) ;
552
+ }
553
+ }
554
+ }
555
+
556
+ /// A root certificate store.
557
+ /// <https://docs.rs/rustls/latest/rustls/struct.RootCertStore.html>
558
+ pub struct rustls_root_cert_store {
559
+ // We use the opaque struct pattern to tell C about our types without
560
+ // telling them what's inside.
561
+ // https://doc.rust-lang.org/nomicon/ffi.html#representing-opaque-structs
562
+ _private : [ u8 ; 0 ] ,
563
+ }
564
+
565
+ impl CastPtr for rustls_root_cert_store {
566
+ type RustType = RootCertStore ;
567
+ }
568
+
569
+ impl ArcCastPtr for rustls_root_cert_store { }
570
+
571
+ impl rustls_root_cert_store {
499
572
/// Free a rustls_root_cert_store previously returned from rustls_root_cert_store_builder_build.
500
573
/// Calling with NULL is fine. Must not be called twice with the same value.
501
574
#[ no_mangle]
0 commit comments