@@ -6,6 +6,7 @@ use super::aead::Counter;
6
6
use super :: { Aad , Algorithm , Invalid , Key , Nonce , BUF_SIZE , MAX_BUF_SIZE } ;
7
7
use std:: io;
8
8
use std:: io:: Write ;
9
+ use std:: thread:: panicking;
9
10
10
11
/// Wraps a writer and encrypts and authenticates everything written to it.
11
12
///
@@ -72,11 +73,6 @@ pub struct EncWriter<A: Algorithm, W: Write + internal::Close> {
72
73
// EncWriter again. This flag tells the Drop impl if it should skip the
73
74
// close.
74
75
closed : bool ,
75
-
76
- // If the inner writer panics in a call to write, we don't want to
77
- // write the buffered data a second time in EncWriter's destructor. This
78
- // flag tells the Drop impl if it should skip the close.
79
- panicked : bool ,
80
76
}
81
77
82
78
impl < A : Algorithm , W : Write + internal:: Close > EncWriter < A , W > {
@@ -200,7 +196,6 @@ impl<A: Algorithm, W: Write + internal::Close> EncWriter<A, W> {
200
196
aad : associated_data,
201
197
errored : false ,
202
198
closed : false ,
203
- panicked : false ,
204
199
} )
205
200
}
206
201
@@ -218,16 +213,33 @@ impl<A: Algorithm, W: Write + internal::Close> EncWriter<A, W> {
218
213
/// Encrypt and authenticate the buffer and write the ciphertext
219
214
/// to the inner writer.
220
215
fn write_buffer ( & mut self , len : usize ) -> io:: Result < ( ) > {
221
- let ciphertext = self . algorithm . seal_in_place (
222
- self . nonce . next ( ) ?,
216
+ let nonce = match self . nonce . next ( ) {
217
+ Ok ( nonce) => nonce,
218
+ Err ( err) => {
219
+ self . errored = true ;
220
+ return Err ( err. into ( ) ) ;
221
+ }
222
+ } ;
223
+
224
+ let ciphertext = match self . algorithm . seal_in_place (
225
+ nonce,
223
226
& self . aad ,
224
227
& mut self . buffer [ ..len + A :: TAG_LEN ] ,
225
- ) ?;
228
+ ) {
229
+ Ok ( ciphertext) => ciphertext,
230
+ Err ( err) => {
231
+ self . errored = true ;
232
+ return Err ( err. into ( ) ) ;
233
+ }
234
+ } ;
226
235
227
- self . panicked = true ;
228
- let r = self . inner . write_all ( ciphertext) ;
229
- self . panicked = false ;
230
- r
236
+ match self . inner . write_all ( ciphertext) {
237
+ Ok ( v) => Ok ( v) ,
238
+ Err ( err) => {
239
+ self . errored = true ;
240
+ Err ( err)
241
+ }
242
+ }
231
243
}
232
244
}
233
245
@@ -237,36 +249,32 @@ impl<A: Algorithm, W: Write + internal::Close> Write for EncWriter<A, W> {
237
249
return Err ( io:: Error :: from ( io:: ErrorKind :: Other ) ) ;
238
250
}
239
251
240
- let r: io:: Result < usize > = {
241
- let n = buf. len ( ) ;
242
-
243
- let remaining = self . buf_size - self . pos ;
244
- if buf. len ( ) <= remaining {
245
- self . buffer [ self . pos ..self . pos + buf. len ( ) ] . copy_from_slice ( buf) ;
246
- self . pos += buf. len ( ) ;
247
- return Ok ( buf. len ( ) ) ;
248
- }
252
+ let n = buf. len ( ) ;
253
+ let remaining = self . buf_size - self . pos ;
254
+ if n <= remaining {
255
+ self . buffer [ self . pos ..self . pos + n] . copy_from_slice ( buf) ;
256
+ self . pos += n;
257
+ return Ok ( n) ;
258
+ }
249
259
250
- self . buffer [ self . pos ..self . buf_size ] . copy_from_slice ( & buf[ ..remaining] ) ;
251
- self . write_buffer ( self . buf_size ) ?;
252
- self . pos = 0 ;
253
-
254
- let buf = & buf[ remaining..] ;
255
- let chunks = buf. chunks ( self . buf_size ) ;
256
- chunks
257
- . clone ( )
258
- . take ( chunks. len ( ) - 1 ) // Since we take only n-1 elements...
259
- . try_for_each ( |chunk| {
260
- self . buffer [ ..self . buf_size ] . copy_from_slice ( chunk) ;
261
- self . write_buffer ( self . buf_size )
262
- } ) ?;
263
- let last = chunks. last ( ) . unwrap ( ) ; // ... thereis always a last one.
264
- self . buffer [ ..last. len ( ) ] . copy_from_slice ( last) ; // ... there is always a last one.
265
- self . pos = last. len ( ) ;
266
- Ok ( n)
267
- } ;
268
- self . errored = r. is_err ( ) ;
269
- r
260
+ self . buffer [ self . pos ..self . buf_size ] . copy_from_slice ( & buf[ ..remaining] ) ;
261
+ self . write_buffer ( self . buf_size ) ?;
262
+ self . pos = 0 ;
263
+ let buf = & buf[ remaining..] ;
264
+
265
+ let chunks = buf. chunks ( self . buf_size ) ;
266
+ chunks
267
+ . clone ( )
268
+ . take ( chunks. len ( ) - 1 ) // Since we take only n-1 elements...
269
+ . try_for_each ( |chunk| {
270
+ self . buffer [ ..self . buf_size ] . copy_from_slice ( chunk) ;
271
+ self . write_buffer ( self . buf_size )
272
+ } ) ?;
273
+
274
+ let last = chunks. last ( ) . unwrap ( ) ; // ... thereis always a last one.
275
+ self . buffer [ ..last. len ( ) ] . copy_from_slice ( last) ; // ... there is always a last one.
276
+ self . pos = last. len ( ) ;
277
+ Ok ( n)
270
278
}
271
279
272
280
#[ inline]
@@ -278,10 +286,7 @@ impl<A: Algorithm, W: Write + internal::Close> Write for EncWriter<A, W> {
278
286
if self . errored {
279
287
return Err ( io:: Error :: from ( io:: ErrorKind :: Other ) ) ;
280
288
}
281
- self . panicked = true ;
282
289
let r = self . inner . flush ( ) ;
283
- self . panicked = false ;
284
-
285
290
self . errored = r. is_err ( ) ;
286
291
r
287
292
}
@@ -302,29 +307,16 @@ impl<A: Algorithm, W: Write + internal::Close> internal::Close for EncWriter<A,
302
307
303
308
impl < A : Algorithm , W : Write + internal:: Close > Drop for EncWriter < A , W > {
304
309
fn drop ( & mut self ) {
305
- // We must not check whether the EncWriter has been closed if:
306
- // - a inner write or flush call panic'd.
307
- // - we encountered an error during a write or flush call.
308
- if !self . panicked && !self . errored {
309
- // For debugging purposes, we allow disabling the panic
310
- // for debug builds - but only if the feature "debug_panic"
311
- // is turned on.
312
- if !( cfg ! ( debug_assertions) && cfg ! ( feature = "debug_panic" ) ) {
313
- // Actually, Drop implementations should not panic.
314
- // However, not closing the EncWriter (see: close())
315
- // implies not encrypting the entire plaintext such that
316
- // the ciphertext written to the inner writer cannot be
317
- // decrypted anymore. Consequently, we would "loose" data.
318
- //
319
- // We could call close() here if it hasn't been called explicitly
320
- // by callers but that would only succeed if no other I/O error
321
- // occurs. Otherwise, we are in the same situation as before. Calling
322
- // close() here would be an optimistic approach - while in cryptography
323
- // we have to be pessimistic.
324
- assert ! (
325
- self . closed,
326
- "EncWriter must be closed explicitly via the close method before being dropped!"
327
- ) ;
310
+ // We must not check whether the EncWriter has been closed if
311
+ // we encountered an error during a write or flush call.
312
+ if !self . errored {
313
+ if !self . closed {
314
+ // We don't want to panic again if some code (between
315
+ // EncWriter::new(...) and EncWriter.close()) already
316
+ // panic'd. Otherwise we would cause a "double-panic".
317
+ if !panicking ( ) {
318
+ panic ! ( "EncWriter must be closed explicitly via the close method before being dropped!" )
319
+ }
328
320
}
329
321
}
330
322
}
@@ -396,11 +388,6 @@ pub struct DecWriter<A: Algorithm, W: Write + internal::Close> {
396
388
// EncWriter again. This flag tells the Drop impl if it should skip the
397
389
// close.
398
390
closed : bool ,
399
-
400
- // If the inner writer panics in a call to write, we don't want to
401
- // write the buffered data a second time in DecWriter's destructor. This
402
- // flag tells the Drop impl if it should skip the close.
403
- panicked : bool ,
404
391
}
405
392
406
393
impl < A : Algorithm , W : Write + internal:: Close > DecWriter < A , W > {
@@ -529,7 +516,6 @@ impl<A: Algorithm, W: Write + internal::Close> DecWriter<A, W> {
529
516
aad : associated_data,
530
517
errored : false ,
531
518
closed : false ,
532
- panicked : false ,
533
519
} )
534
520
}
535
521
@@ -547,14 +533,33 @@ impl<A: Algorithm, W: Write + internal::Close> DecWriter<A, W> {
547
533
/// Decrypt and verifies the buffer and write the plaintext
548
534
/// to the inner writer.
549
535
fn write_buffer ( & mut self , len : usize ) -> io:: Result < ( ) > {
550
- let plaintext =
551
- self . algorithm
552
- . open_in_place ( self . nonce . next ( ) ?, & self . aad , & mut self . buffer [ ..len] ) ?;
536
+ let nonce = match self . nonce . next ( ) {
537
+ Ok ( nonce) => nonce,
538
+ Err ( err) => {
539
+ self . errored = true ;
540
+ return Err ( err. into ( ) ) ;
541
+ }
542
+ } ;
553
543
554
- self . panicked = true ;
555
- let r = self . inner . write_all ( plaintext) ;
556
- self . panicked = false ;
557
- r
544
+ let plaintext =
545
+ match self
546
+ . algorithm
547
+ . open_in_place ( nonce, & self . aad , & mut self . buffer [ ..len] )
548
+ {
549
+ Ok ( plaintext) => plaintext,
550
+ Err ( err) => {
551
+ self . errored = true ;
552
+ return Err ( err. into ( ) ) ;
553
+ }
554
+ } ;
555
+
556
+ match self . inner . write_all ( plaintext) {
557
+ Ok ( v) => Ok ( v) ,
558
+ Err ( err) => {
559
+ self . errored = true ;
560
+ Err ( err)
561
+ }
562
+ }
558
563
}
559
564
}
560
565
@@ -563,37 +568,33 @@ impl<A: Algorithm, W: Write + internal::Close> Write for DecWriter<A, W> {
563
568
if self . errored {
564
569
return Err ( io:: Error :: from ( io:: ErrorKind :: Other ) ) ;
565
570
}
566
- let r: io:: Result < usize > = {
567
- let n = buf. len ( ) ;
568
-
569
- let remaining = self . buf_size + A :: TAG_LEN - self . pos ;
570
- if buf. len ( ) <= remaining {
571
- self . buffer [ self . pos ..self . pos + buf. len ( ) ] . copy_from_slice ( buf) ;
572
- self . pos += buf. len ( ) ;
573
- return Ok ( n) ;
574
- }
575
571
576
- self . buffer [ self . pos ..] . copy_from_slice ( & buf[ ..remaining] ) ;
577
- self . write_buffer ( self . buf_size + A :: TAG_LEN ) ?;
578
- self . pos = 0 ;
579
-
580
- let buf = & buf[ remaining..] ;
581
- let chunks = buf. chunks ( self . buf_size + A :: TAG_LEN ) ;
582
- chunks
583
- . clone ( )
584
- . take ( chunks. len ( ) - 1 ) // Since we take only n-1 elements...
585
- . try_for_each ( |chunk| {
586
- self . buffer . copy_from_slice ( chunk) ;
587
- self . write_buffer ( self . buf_size + A :: TAG_LEN )
588
- } ) ?;
589
- let last = chunks. last ( ) . unwrap ( ) ; // ... there is always a last one.
590
- self . buffer [ ..last. len ( ) ] . copy_from_slice ( last) ;
591
- self . pos = last. len ( ) ;
592
- Ok ( n)
593
- } ;
572
+ let n = buf. len ( ) ;
573
+ let remaining = self . buf_size + A :: TAG_LEN - self . pos ;
574
+ if n <= remaining {
575
+ self . buffer [ self . pos ..self . pos + n] . copy_from_slice ( buf) ;
576
+ self . pos += n;
577
+ return Ok ( n) ;
578
+ }
594
579
595
- self . errored = r. is_err ( ) ;
596
- r
580
+ self . buffer [ self . pos ..] . copy_from_slice ( & buf[ ..remaining] ) ;
581
+ self . write_buffer ( self . buf_size + A :: TAG_LEN ) ?;
582
+ self . pos = 0 ;
583
+ let buf = & buf[ remaining..] ;
584
+
585
+ let chunks = buf. chunks ( self . buf_size + A :: TAG_LEN ) ;
586
+ chunks
587
+ . clone ( )
588
+ . take ( chunks. len ( ) - 1 ) // Since we take only n-1 elements...
589
+ . try_for_each ( |chunk| {
590
+ self . buffer . copy_from_slice ( chunk) ;
591
+ self . write_buffer ( self . buf_size + A :: TAG_LEN )
592
+ } ) ?;
593
+
594
+ let last = chunks. last ( ) . unwrap ( ) ; // ... there is always a last one.
595
+ self . buffer [ ..last. len ( ) ] . copy_from_slice ( last) ;
596
+ self . pos = last. len ( ) ;
597
+ Ok ( n)
597
598
}
598
599
599
600
#[ inline]
@@ -605,10 +606,7 @@ impl<A: Algorithm, W: Write + internal::Close> Write for DecWriter<A, W> {
605
606
if self . errored {
606
607
return Err ( io:: Error :: from ( io:: ErrorKind :: Other ) ) ;
607
608
}
608
- self . panicked = true ;
609
609
let r = self . inner . flush ( ) ;
610
- self . panicked = false ;
611
-
612
610
self . errored = r. is_err ( ) ;
613
611
r
614
612
}
@@ -629,31 +627,16 @@ impl<A: Algorithm, W: Write + internal::Close> internal::Close for DecWriter<A,
629
627
630
628
impl < A : Algorithm , W : Write + internal:: Close > Drop for DecWriter < A , W > {
631
629
fn drop ( & mut self ) {
632
- // We must not check whether the DecWriter has been closed if:
633
- // - a inner write or flush call panic'd.
634
- // - we encountered an error during a write or flush call.
635
- if !self . panicked && !self . errored {
636
- // For debugging purposes,we allow disabling the panic
637
- // for debug builds - but only if the feature "debug_panic"
638
- // is turned on.
639
- if !( cfg ! ( debug_assertions) && cfg ! ( feature = "debug_panic" ) ) {
640
- // Actually, Drop implementations should not panic.
641
- // However, not closing the DecWriter (see: close())
642
- // implies not decrypting the entire ciphertext and
643
- // also not writing the entire plaintext to the inner
644
- // writer. Consequently, not calling close causes not
645
- // authentic (b/c incomplete) plaintext output.
646
- //
647
- // We could call close() here if it hasn't been called explicitly
648
- // by callers but that would only succeed if the ciphertext
649
- // is authentic and no other I/O error occurs. Otherwise, we
650
- // are in the same situation as before. Calling close() here
651
- // would be an optimistic approach - while in cryptography we have
652
- // to be pessimistic.
653
- assert ! (
654
- self . closed,
655
- "DecWriter must be closed explicitly via the close method before being dropped!"
656
- ) ;
630
+ // We must not check whether the DecWriter has been closed if
631
+ // we encountered an error during a write or flush call.
632
+ if !self . errored {
633
+ if !self . closed {
634
+ // We don't want to panic again if some code (between
635
+ // DecWriter::new(...) and DecWriter.close()) already
636
+ // panic'd. Otherwise we would cause a "double-panic".
637
+ if !panicking ( ) {
638
+ panic ! ( "DecWriter must be closed explicitly via the close method before being dropped!" )
639
+ }
657
640
}
658
641
}
659
642
}
0 commit comments