@@ -251,56 +251,38 @@ mod aarch64;
251
251
#[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
252
252
mod x86;
253
253
254
- use core:: marker:: { PhantomData , PhantomPinned } ;
255
- use core:: mem:: { self , MaybeUninit } ;
256
- use core:: num:: {
257
- NonZeroI128 , NonZeroI16 , NonZeroI32 , NonZeroI64 , NonZeroI8 , NonZeroIsize , NonZeroU128 ,
258
- NonZeroU16 , NonZeroU32 , NonZeroU64 , NonZeroU8 , NonZeroUsize ,
254
+ use core:: {
255
+ marker:: { PhantomData , PhantomPinned } ,
256
+ mem:: { self , MaybeUninit } ,
257
+ num:: {
258
+ NonZeroI128 , NonZeroI16 , NonZeroI32 , NonZeroI64 , NonZeroI8 , NonZeroIsize , NonZeroU128 ,
259
+ NonZeroU16 , NonZeroU32 , NonZeroU64 , NonZeroU8 , NonZeroUsize ,
260
+ } ,
261
+ ops, ptr,
262
+ slice:: IterMut ,
263
+ sync:: atomic,
259
264
} ;
260
- use core:: { ops, ptr, slice:: IterMut , sync:: atomic} ;
261
265
262
266
#[ cfg( feature = "alloc" ) ]
263
- use alloc:: { boxed:: Box , string:: String , vec:: Vec } ;
267
+ use {
268
+ alloc:: { boxed:: Box , string:: String , vec:: Vec } ,
269
+ core:: slice,
270
+ } ;
264
271
265
272
#[ cfg( feature = "std" ) ]
266
273
use std:: ffi:: CString ;
267
274
268
- /// Trait for securely erasing types from memory
275
+ /// Trait for securely erasing values from memory.
269
276
pub trait Zeroize {
270
277
/// Zero out this object from memory using Rust intrinsics which ensure the
271
278
/// zeroization operation is not "optimized away" by the compiler.
272
279
fn zeroize ( & mut self ) ;
273
280
}
274
281
275
- /// Marker trait signifying that this type will [`zeroize`]( Zeroize::zeroize) itself on [`Drop`].
282
+ /// Marker trait signifying that this type will [`Zeroize::zeroize`] itself on [`Drop`].
276
283
pub trait ZeroizeOnDrop { }
277
284
278
- #[ doc( hidden) ]
279
- pub mod __internal {
280
- use super :: * ;
281
-
282
- /// Auto-deref workaround for deriving `ZeroizeOnDrop`.
283
- pub trait AssertZeroizeOnDrop {
284
- fn zeroize_or_on_drop ( self ) ;
285
- }
286
-
287
- impl < T : ZeroizeOnDrop + ?Sized > AssertZeroizeOnDrop for & & mut T {
288
- fn zeroize_or_on_drop ( self ) { }
289
- }
290
-
291
- /// Auto-deref workaround for deriving `ZeroizeOnDrop`.
292
- pub trait AssertZeroize {
293
- fn zeroize_or_on_drop ( & mut self ) ;
294
- }
295
-
296
- impl < T : Zeroize + ?Sized > AssertZeroize for T {
297
- fn zeroize_or_on_drop ( & mut self ) {
298
- self . zeroize ( )
299
- }
300
- }
301
- }
302
-
303
- /// Marker trait for types whose `Default` is the desired zeroization result
285
+ /// Marker trait for types whose [`Default`] is the desired zeroization result
304
286
pub trait DefaultIsZeroes : Copy + Default + Sized { }
305
287
306
288
impl < Z > Zeroize for Z
@@ -319,19 +301,24 @@ macro_rules! impl_zeroize_with_default {
319
301
} ;
320
302
}
321
303
322
- impl_zeroize_with_default ! ( i8 , i16 , i32 , i64 , i128 , isize ) ;
323
- impl_zeroize_with_default ! ( u8 , u16 , u32 , u64 , u128 , usize ) ;
324
- impl_zeroize_with_default ! ( f32 , f64 , char , bool ) ;
304
+ #[ rustfmt:: skip]
305
+ impl_zeroize_with_default ! {
306
+ bool , char ,
307
+ f32 , f64 ,
308
+ i8 , i16 , i32 , i64 , i128 , isize ,
309
+ u8 , u16 , u32 , u64 , u128 , usize
310
+ }
325
311
326
312
macro_rules! impl_zeroize_for_non_zero {
327
313
( $( $type: ty) ,+) => {
328
- $( impl Zeroize for $type
329
- {
330
- fn zeroize( & mut self ) {
331
- volatile_write( self , unsafe { <$type>:: new_unchecked( 1 ) } ) ;
332
- atomic_fence( ) ;
314
+ $(
315
+ impl Zeroize for $type {
316
+ fn zeroize( & mut self ) {
317
+ volatile_write( self , unsafe { <$type>:: new_unchecked( 1 ) } ) ;
318
+ atomic_fence( ) ;
319
+ }
333
320
}
334
- } ) +
321
+ ) +
335
322
} ;
336
323
}
337
324
@@ -341,9 +328,7 @@ impl_zeroize_for_non_zero!(
341
328
NonZeroI32 ,
342
329
NonZeroI64 ,
343
330
NonZeroI128 ,
344
- NonZeroIsize
345
- ) ;
346
- impl_zeroize_for_non_zero ! (
331
+ NonZeroIsize ,
347
332
NonZeroU8 ,
348
333
NonZeroU16 ,
349
334
NonZeroU32 ,
@@ -352,7 +337,7 @@ impl_zeroize_for_non_zero!(
352
337
NonZeroUsize
353
338
) ;
354
339
355
- /// Implement `Zeroize` on arrays of types that impl `Zeroize`
340
+ /// Impl [ `Zeroize`] on arrays of types that impl [ `Zeroize`].
356
341
impl < Z , const N : usize > Zeroize for [ Z ; N ]
357
342
where
358
343
Z : Zeroize ,
@@ -361,7 +346,8 @@ where
361
346
self . iter_mut ( ) . zeroize ( ) ;
362
347
}
363
348
}
364
- /// Implement `ZeroizeOnDrop` on arrays of types that impl `ZeroizeOnDrop`
349
+
350
+ /// Impl [`ZeroizeOnDrop`] on arrays of types that impl [`ZeroizeOnDrop`].
365
351
impl < Z , const N : usize > ZeroizeOnDrop for [ Z ; N ] where Z : ZeroizeOnDrop { }
366
352
367
353
impl < ' a , Z > Zeroize for IterMut < ' a , Z >
@@ -417,16 +403,21 @@ where
417
403
418
404
impl < Z > ZeroizeOnDrop for Option < Z > where Z : ZeroizeOnDrop { }
419
405
420
- /// Impl `Zeroize` on slices of MaybeUninit types
406
+ /// Impl [`Zeroize`] on slices of [`MaybeUninit`] types.
407
+ ///
421
408
/// This impl can eventually be optimized using an memset intrinsic,
422
- /// such as `core::intrinsics::volatile_set_memory`.
423
- /// This fills the slice with zeros
424
- /// Note that this ignore invariants that Z might have, because MaybeUninit removes all invariants.
409
+ /// such as [`core::intrinsics::volatile_set_memory`].
410
+ ///
411
+ /// This fills the slice with zeroes.
412
+ ///
413
+ /// Note that this ignore invariants that `Z` might have, because
414
+ /// [`MaybeUninit`] removes all invariants.
425
415
impl < Z > Zeroize for [ MaybeUninit < Z > ] {
426
416
fn zeroize ( & mut self ) {
427
417
let ptr = self . as_mut_ptr ( ) as * mut MaybeUninit < u8 > ;
428
418
let size = self . len ( ) . checked_mul ( mem:: size_of :: < Z > ( ) ) . unwrap ( ) ;
429
- assert ! ( size <= core:: isize :: MAX as usize ) ;
419
+ assert ! ( size <= isize :: MAX as usize ) ;
420
+
430
421
// Safety:
431
422
//
432
423
// This is safe, because every valid pointer is well aligned for u8
@@ -438,20 +429,21 @@ impl<Z> Zeroize for [MaybeUninit<Z>] {
438
429
}
439
430
}
440
431
441
- /// Impl `Zeroize` on slices of types that can be zeroized with `Default`.
432
+ /// Impl [ `Zeroize`] on slices of types that can be zeroized with [ `Default`] .
442
433
///
443
434
/// This impl can eventually be optimized using an memset intrinsic,
444
- /// such as `core::intrinsics::volatile_set_memory`. For that reason the blanket
445
- /// impl on slices is bounded by `DefaultIsZeroes`.
435
+ /// such as [ `core::intrinsics::volatile_set_memory`] . For that reason the
436
+ /// blanket impl on slices is bounded by [ `DefaultIsZeroes`] .
446
437
///
447
438
/// To zeroize a mut slice of `Z: Zeroize` which does not impl
448
- /// `DefaultIsZeroes`, call `iter_mut().zeroize()`.
439
+ /// [ `DefaultIsZeroes`] , call `iter_mut().zeroize()`.
449
440
impl < Z > Zeroize for [ Z ]
450
441
where
451
442
Z : DefaultIsZeroes ,
452
443
{
453
444
fn zeroize ( & mut self ) {
454
- assert ! ( self . len( ) <= core:: isize :: MAX as usize ) ;
445
+ assert ! ( self . len( ) <= isize :: MAX as usize ) ;
446
+
455
447
// Safety:
456
448
//
457
449
// This is safe, because the slice is well aligned and is backed by a single allocated
@@ -463,6 +455,65 @@ where
463
455
}
464
456
}
465
457
458
+ /// [`PhantomData`] is always zero sized so provide a [`Zeroize`] implementation.
459
+ impl < Z > Zeroize for PhantomData < Z > {
460
+ fn zeroize ( & mut self ) { }
461
+ }
462
+
463
+ /// [`PhantomData` is always zero sized so provide a ZeroizeOnDrop implementation.
464
+ impl < Z > ZeroizeOnDrop for PhantomData < Z > { }
465
+
466
+ /// `PhantomPinned` is zero sized so provide a Zeroize implementation.
467
+ impl Zeroize for PhantomPinned {
468
+ fn zeroize ( & mut self ) { }
469
+ }
470
+
471
+ /// `PhantomPinned` is zero sized so provide a ZeroizeOnDrop implementation.
472
+ impl ZeroizeOnDrop for PhantomPinned { }
473
+
474
+ /// `()` is zero sized so provide a Zeroize implementation.
475
+ impl Zeroize for ( ) {
476
+ fn zeroize ( & mut self ) { }
477
+ }
478
+
479
+ /// `()` is zero sized so provide a ZeroizeOnDrop implementation.
480
+ impl ZeroizeOnDrop for ( ) { }
481
+
482
+ /// Generic implementation of Zeroize for tuples up to 10 parameters.
483
+ impl < A : Zeroize > Zeroize for ( A , ) {
484
+ fn zeroize ( & mut self ) {
485
+ self . 0 . zeroize ( ) ;
486
+ }
487
+ }
488
+
489
+ /// Generic implementation of ZeroizeOnDrop for tuples up to 10 parameters.
490
+ impl < A : ZeroizeOnDrop > ZeroizeOnDrop for ( A , ) { }
491
+
492
+ macro_rules! impl_zeroize_tuple {
493
+ ( $( $type_name: ident ) ,+ ) => {
494
+ impl <$( $type_name: Zeroize ) ,+> Zeroize for ( $( $type_name) ,+) {
495
+ fn zeroize( & mut self ) {
496
+ #[ allow( non_snake_case) ]
497
+ let ( $( $type_name) ,+) = self ;
498
+ $( $type_name. zeroize( ) ) ;+
499
+ }
500
+ }
501
+
502
+ impl <$( $type_name: ZeroizeOnDrop ) ,+> ZeroizeOnDrop for ( $( $type_name) ,+) { }
503
+ }
504
+ }
505
+
506
+ // Generic implementations for tuples up to 10 parameters.
507
+ impl_zeroize_tuple ! ( A , B ) ;
508
+ impl_zeroize_tuple ! ( A , B , C ) ;
509
+ impl_zeroize_tuple ! ( A , B , C , D ) ;
510
+ impl_zeroize_tuple ! ( A , B , C , D , E ) ;
511
+ impl_zeroize_tuple ! ( A , B , C , D , E , F ) ;
512
+ impl_zeroize_tuple ! ( A , B , C , D , E , F , G ) ;
513
+ impl_zeroize_tuple ! ( A , B , C , D , E , F , G , H ) ;
514
+ impl_zeroize_tuple ! ( A , B , C , D , E , F , G , H , I ) ;
515
+ impl_zeroize_tuple ! ( A , B , C , D , E , F , G , H , I , J ) ;
516
+
466
517
#[ cfg( feature = "alloc" ) ]
467
518
#[ cfg_attr( docsrs, doc( cfg( feature = "alloc" ) ) ) ]
468
519
impl < Z > Zeroize for Vec < Z >
@@ -474,12 +525,12 @@ where
474
525
/// Ensures the entire capacity of the `Vec` is zeroed. Cannot ensure that
475
526
/// previous reallocations did not leave values on the heap.
476
527
fn zeroize ( & mut self ) {
477
- use core:: slice;
478
528
// Zeroize all the initialized elements.
479
529
self . iter_mut ( ) . zeroize ( ) ;
480
530
481
531
// Set the Vec's length to 0 and drop all the elements.
482
532
self . clear ( ) ;
533
+
483
534
// Zero the full capacity of `Vec`.
484
535
// Safety:
485
536
//
@@ -490,6 +541,7 @@ where
490
541
let uninit_slice = unsafe {
491
542
slice:: from_raw_parts_mut ( self . as_mut_ptr ( ) as * mut MaybeUninit < Z > , self . capacity ( ) )
492
543
} ;
544
+
493
545
uninit_slice. zeroize ( ) ;
494
546
}
495
547
}
@@ -530,17 +582,20 @@ impl Zeroize for CString {
530
582
// mem::take uses replace internally to swap the pointer
531
583
// Unfortunately this results in an allocation for a Box::new(&[0]) as CString must
532
584
// contain a trailing zero byte
533
- let this = std:: mem:: take ( self ) ;
585
+ let this = mem:: take ( self ) ;
586
+
534
587
// - CString::into_bytes calls ::into_vec which takes ownership of the heap pointer
535
588
// as a Vec<u8>
536
589
// - Calling .zeroize() on the resulting vector clears out the bytes
537
590
// From: https://github.com/RustCrypto/utils/pull/759#issuecomment-1087976570
538
591
let mut buf = this. into_bytes ( ) ;
539
592
buf. zeroize ( ) ;
593
+
540
594
// expect() should never fail, because zeroize() truncates the Vec
541
595
let zeroed = CString :: new ( buf) . expect ( "buf not truncated" ) ;
596
+
542
597
// Replace self by the zeroed CString to maintain the original ptr of the buffer
543
- let _ = std :: mem:: replace ( self , zeroed) ;
598
+ let _ = mem:: replace ( self , zeroed) ;
544
599
}
545
600
}
546
601
@@ -685,6 +740,7 @@ unsafe fn volatile_set<T: Copy + Sized>(dst: *mut T, src: T, count: usize) {
685
740
// allocation pointed to by `dst`, because `count <= isize::MAX` and because
686
741
// `dst.add(count)` must not wrap around the address space.
687
742
let ptr = dst. add ( i) ;
743
+
688
744
// Safety:
689
745
//
690
746
// This is safe, because the pointer is valid and because `dst` is well aligned for `T` and
@@ -693,56 +749,31 @@ unsafe fn volatile_set<T: Copy + Sized>(dst: *mut T, src: T, count: usize) {
693
749
}
694
750
}
695
751
696
- /// `PhantomData` is always zero sized so provide a Zeroize implementation.
697
- impl < Z > Zeroize for PhantomData < Z > {
698
- fn zeroize ( & mut self ) { }
699
- }
700
- /// `PhantomData` is always zero sized so provide a ZeroizeOnDrop implementation.
701
- impl < Z > ZeroizeOnDrop for PhantomData < Z > { }
702
- /// `PhantomPinned` is zero sized so provide a Zeroize implementation.
703
- impl Zeroize for PhantomPinned {
704
- fn zeroize ( & mut self ) { }
705
- }
706
- /// `PhantomPinned` is zero sized so provide a ZeroizeOnDrop implementation.
707
- impl ZeroizeOnDrop for PhantomPinned { }
708
- /// `()` is zero sized so provide a Zeroize implementation.
709
- impl Zeroize for ( ) {
710
- fn zeroize ( & mut self ) { }
711
- }
712
- /// `()` is zero sized so provide a ZeroizeOnDrop implementation.
713
- impl ZeroizeOnDrop for ( ) { }
752
+ /// Internal module used as support for `AssertZeroizeOnDrop`.
753
+ #[ doc( hidden) ]
754
+ pub mod __internal {
755
+ use super :: * ;
714
756
715
- /// Generic implementation of Zeroize for tuples up to 10 parameters.
716
- impl < A : Zeroize > Zeroize for ( A , ) {
717
- fn zeroize ( & mut self ) {
718
- self . 0 . zeroize ( ) ;
757
+ /// Auto-deref workaround for deriving `ZeroizeOnDrop`.
758
+ pub trait AssertZeroizeOnDrop {
759
+ fn zeroize_or_on_drop ( self ) ;
719
760
}
720
- }
721
- /// Generic implementation of ZeroizeOnDrop for tuples up to 10 parameters.
722
- impl < A : ZeroizeOnDrop > ZeroizeOnDrop for ( A , ) { }
723
- macro_rules! impl_zeroize_tuple {
724
- ( $( $type_name: ident ) + ) => {
725
- impl <$( $type_name: Zeroize ) ,+> Zeroize for ( $( $type_name) ,+) {
726
- fn zeroize( & mut self ) {
727
- #[ allow( non_snake_case) ]
728
- let ( $( $type_name) ,+) = self ;
729
- $( $type_name. zeroize( ) ) ;+
730
- }
731
- }
732
761
733
- impl <$( $type_name: ZeroizeOnDrop ) ,+> ZeroizeOnDrop for ( $( $type_name) ,+) { }
762
+ impl < T : ZeroizeOnDrop + ?Sized > AssertZeroizeOnDrop for & & mut T {
763
+ fn zeroize_or_on_drop ( self ) { }
764
+ }
765
+
766
+ /// Auto-deref workaround for deriving `ZeroizeOnDrop`.
767
+ pub trait AssertZeroize {
768
+ fn zeroize_or_on_drop ( & mut self ) ;
769
+ }
770
+
771
+ impl < T : Zeroize + ?Sized > AssertZeroize for T {
772
+ fn zeroize_or_on_drop ( & mut self ) {
773
+ self . zeroize ( )
774
+ }
734
775
}
735
776
}
736
- // Generic implementations for tuples up to 10 parameters.
737
- impl_zeroize_tuple ! { A B }
738
- impl_zeroize_tuple ! { A B C }
739
- impl_zeroize_tuple ! { A B C D }
740
- impl_zeroize_tuple ! { A B C D E }
741
- impl_zeroize_tuple ! { A B C D E F }
742
- impl_zeroize_tuple ! { A B C D E F G }
743
- impl_zeroize_tuple ! { A B C D E F G H }
744
- impl_zeroize_tuple ! { A B C D E F G H I }
745
- impl_zeroize_tuple ! { A B C D E F G H I L }
746
777
747
778
#[ cfg( test) ]
748
779
mod tests {
@@ -784,9 +815,7 @@ mod tests {
784
815
NonZeroI32 ,
785
816
NonZeroI64 ,
786
817
NonZeroI128 ,
787
- NonZeroIsize
788
- ) ;
789
- non_zero_test ! (
818
+ NonZeroIsize ,
790
819
NonZeroU8 ,
791
820
NonZeroU16 ,
792
821
NonZeroU32 ,
0 commit comments