@@ -84,7 +84,7 @@ static S7:u32x4 = u32x4(7, 7, 7, 7);
84
84
impl ChaCha20 {
85
85
pub fn new ( key : & [ u8 ] , nonce : & [ u8 ] ) -> ChaCha20 {
86
86
assert ! ( key. len( ) == 16 || key. len( ) == 32 ) ;
87
- assert ! ( nonce. len( ) == 8 ) ;
87
+ assert ! ( nonce. len( ) == 8 || nonce . len ( ) == 12 ) ;
88
88
89
89
ChaCha20 { state : ChaCha20 :: expand ( key, nonce) , output : [ 0u8 ; 64 ] , offset : 64 }
90
90
}
@@ -124,12 +124,21 @@ impl ChaCha20 {
124
124
read_u32_le ( & key[ 28 ..32 ] )
125
125
)
126
126
} ,
127
- d : u32x4 (
128
- 0 ,
129
- 0 ,
130
- read_u32_le ( & nonce[ 0 ..4 ] ) ,
131
- read_u32_le ( & nonce[ 4 ..8 ] )
132
- )
127
+ d : if nonce. len ( ) == 12 {
128
+ u32x4 (
129
+ 0 ,
130
+ read_u32_le ( & nonce[ 0 ..4 ] ) ,
131
+ read_u32_le ( & nonce[ 4 ..8 ] ) ,
132
+ read_u32_le ( & nonce[ 8 ..12 ] )
133
+ )
134
+ } else {
135
+ u32x4 (
136
+ 0 ,
137
+ 0 ,
138
+ read_u32_le ( & nonce[ 0 ..4 ] ) ,
139
+ read_u32_le ( & nonce[ 4 ..8 ] )
140
+ )
141
+ }
133
142
}
134
143
}
135
144
@@ -153,7 +162,10 @@ impl ChaCha20 {
153
162
self . state . d += u32x4 ( 1 , 0 , 0 , 0 ) ;
154
163
let u32x4( c12, _, _, _) = self . state . d ;
155
164
if c12 == 0 {
156
- self . state . d += u32x4 ( 0 , 1 , 0 , 0 ) ;
165
+ // we could increment the other counter word with an 8 byte nonce
166
+ // but other implementations like boringssl have this same
167
+ // limitation
168
+ panic ! ( "counter is exhausted" ) ;
157
169
}
158
170
159
171
self . offset = 0 ;
@@ -334,6 +346,141 @@ mod test {
334
346
assert_eq ! ( output, tv. keystream) ;
335
347
}
336
348
}
349
+
350
+ #[ test]
351
+ fn test_chacha20_256_tls_vectors_96_nonce ( ) {
352
+ struct TestVector {
353
+ key : [ u8 ; 32 ] ,
354
+ nonce : [ u8 ; 12 ] ,
355
+ keystream : Vec < u8 > ,
356
+ } ;
357
+ // taken from http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04
358
+ let test_vectors = vec ! (
359
+ TestVector {
360
+ key: [
361
+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
362
+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
363
+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
364
+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
365
+ ] ,
366
+ nonce: [ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ] ,
367
+ keystream: vec!(
368
+ 0x76 , 0xb8 , 0xe0 , 0xad , 0xa0 , 0xf1 , 0x3d , 0x90 ,
369
+ 0x40 , 0x5d , 0x6a , 0xe5 , 0x53 , 0x86 , 0xbd , 0x28 ,
370
+ 0xbd , 0xd2 , 0x19 , 0xb8 , 0xa0 , 0x8d , 0xed , 0x1a ,
371
+ 0xa8 , 0x36 , 0xef , 0xcc , 0x8b , 0x77 , 0x0d , 0xc7 ,
372
+ 0xda , 0x41 , 0x59 , 0x7c , 0x51 , 0x57 , 0x48 , 0x8d ,
373
+ 0x77 , 0x24 , 0xe0 , 0x3f , 0xb8 , 0xd8 , 0x4a , 0x37 ,
374
+ 0x6a , 0x43 , 0xb8 , 0xf4 , 0x15 , 0x18 , 0xa1 , 0x1c ,
375
+ 0xc3 , 0x87 , 0xb6 , 0x69 , 0xb2 , 0xee , 0x65 , 0x86 ,
376
+ ) ,
377
+ } , TestVector {
378
+ key: [
379
+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
380
+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
381
+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
382
+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x01 ,
383
+ ] ,
384
+ nonce: [ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ] ,
385
+ keystream: vec!(
386
+ 0x45 , 0x40 , 0xf0 , 0x5a , 0x9f , 0x1f , 0xb2 , 0x96 ,
387
+ 0xd7 , 0x73 , 0x6e , 0x7b , 0x20 , 0x8e , 0x3c , 0x96 ,
388
+ 0xeb , 0x4f , 0xe1 , 0x83 , 0x46 , 0x88 , 0xd2 , 0x60 ,
389
+ 0x4f , 0x45 , 0x09 , 0x52 , 0xed , 0x43 , 0x2d , 0x41 ,
390
+ 0xbb , 0xe2 , 0xa0 , 0xb6 , 0xea , 0x75 , 0x66 , 0xd2 ,
391
+ 0xa5 , 0xd1 , 0xe7 , 0xe2 , 0x0d , 0x42 , 0xaf , 0x2c ,
392
+ 0x53 , 0xd7 , 0x92 , 0xb1 , 0xc4 , 0x3f , 0xea , 0x81 ,
393
+ 0x7e , 0x9a , 0xd2 , 0x75 , 0xae , 0x54 , 0x69 , 0x63 ,
394
+ ) ,
395
+ } , TestVector {
396
+ key: [
397
+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
398
+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
399
+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
400
+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
401
+ ] ,
402
+ nonce: [ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x01 ] ,
403
+ keystream: vec!(
404
+ 0xde , 0x9c , 0xba , 0x7b , 0xf3 , 0xd6 , 0x9e , 0xf5 ,
405
+ 0xe7 , 0x86 , 0xdc , 0x63 , 0x97 , 0x3f , 0x65 , 0x3a ,
406
+ 0x0b , 0x49 , 0xe0 , 0x15 , 0xad , 0xbf , 0xf7 , 0x13 ,
407
+ 0x4f , 0xcb , 0x7d , 0xf1 , 0x37 , 0x82 , 0x10 , 0x31 ,
408
+ 0xe8 , 0x5a , 0x05 , 0x02 , 0x78 , 0xa7 , 0x08 , 0x45 ,
409
+ 0x27 , 0x21 , 0x4f , 0x73 , 0xef , 0xc7 , 0xfa , 0x5b ,
410
+ 0x52 , 0x77 , 0x06 , 0x2e , 0xb7 , 0xa0 , 0x43 , 0x3e ,
411
+ 0x44 , 0x5f , 0x41 , 0xe3 ,
412
+ ) ,
413
+ } , TestVector {
414
+ key: [
415
+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
416
+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
417
+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
418
+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
419
+ ] ,
420
+ nonce: [ 0x00 , 0x00 , 0x00 , 0x00 , 0x01 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ] ,
421
+ keystream: vec!(
422
+ 0xef , 0x3f , 0xdf , 0xd6 , 0xc6 , 0x15 , 0x78 , 0xfb ,
423
+ 0xf5 , 0xcf , 0x35 , 0xbd , 0x3d , 0xd3 , 0x3b , 0x80 ,
424
+ 0x09 , 0x63 , 0x16 , 0x34 , 0xd2 , 0x1e , 0x42 , 0xac ,
425
+ 0x33 , 0x96 , 0x0b , 0xd1 , 0x38 , 0xe5 , 0x0d , 0x32 ,
426
+ 0x11 , 0x1e , 0x4c , 0xaf , 0x23 , 0x7e , 0xe5 , 0x3c ,
427
+ 0xa8 , 0xad , 0x64 , 0x26 , 0x19 , 0x4a , 0x88 , 0x54 ,
428
+ 0x5d , 0xdc , 0x49 , 0x7a , 0x0b , 0x46 , 0x6e , 0x7d ,
429
+ 0x6b , 0xbd , 0xb0 , 0x04 , 0x1b , 0x2f , 0x58 , 0x6b ,
430
+ ) ,
431
+ } , TestVector {
432
+ key: [
433
+ 0x00 , 0x01 , 0x02 , 0x03 , 0x04 , 0x05 , 0x06 , 0x07 ,
434
+ 0x08 , 0x09 , 0x0a , 0x0b , 0x0c , 0x0d , 0x0e , 0x0f ,
435
+ 0x10 , 0x11 , 0x12 , 0x13 , 0x14 , 0x15 , 0x16 , 0x17 ,
436
+ 0x18 , 0x19 , 0x1a , 0x1b , 0x1c , 0x1d , 0x1e , 0x1f ,
437
+ ] ,
438
+ nonce: [ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x01 , 0x02 , 0x03 , 0x04 , 0x05 , 0x06 , 0x07 ] ,
439
+ keystream: vec!(
440
+ 0xf7 , 0x98 , 0xa1 , 0x89 , 0xf1 , 0x95 , 0xe6 , 0x69 ,
441
+ 0x82 , 0x10 , 0x5f , 0xfb , 0x64 , 0x0b , 0xb7 , 0x75 ,
442
+ 0x7f , 0x57 , 0x9d , 0xa3 , 0x16 , 0x02 , 0xfc , 0x93 ,
443
+ 0xec , 0x01 , 0xac , 0x56 , 0xf8 , 0x5a , 0xc3 , 0xc1 ,
444
+ 0x34 , 0xa4 , 0x54 , 0x7b , 0x73 , 0x3b , 0x46 , 0x41 ,
445
+ 0x30 , 0x42 , 0xc9 , 0x44 , 0x00 , 0x49 , 0x17 , 0x69 ,
446
+ 0x05 , 0xd3 , 0xbe , 0x59 , 0xea , 0x1c , 0x53 , 0xf1 ,
447
+ 0x59 , 0x16 , 0x15 , 0x5c , 0x2b , 0xe8 , 0x24 , 0x1a ,
448
+ 0x38 , 0x00 , 0x8b , 0x9a , 0x26 , 0xbc , 0x35 , 0x94 ,
449
+ 0x1e , 0x24 , 0x44 , 0x17 , 0x7c , 0x8a , 0xde , 0x66 ,
450
+ 0x89 , 0xde , 0x95 , 0x26 , 0x49 , 0x86 , 0xd9 , 0x58 ,
451
+ 0x89 , 0xfb , 0x60 , 0xe8 , 0x46 , 0x29 , 0xc9 , 0xbd ,
452
+ 0x9a , 0x5a , 0xcb , 0x1c , 0xc1 , 0x18 , 0xbe , 0x56 ,
453
+ 0x3e , 0xb9 , 0xb3 , 0xa4 , 0xa4 , 0x72 , 0xf8 , 0x2e ,
454
+ 0x09 , 0xa7 , 0xe7 , 0x78 , 0x49 , 0x2b , 0x56 , 0x2e ,
455
+ 0xf7 , 0x13 , 0x0e , 0x88 , 0xdf , 0xe0 , 0x31 , 0xc7 ,
456
+ 0x9d , 0xb9 , 0xd4 , 0xf7 , 0xc7 , 0xa8 , 0x99 , 0x15 ,
457
+ 0x1b , 0x9a , 0x47 , 0x50 , 0x32 , 0xb6 , 0x3f , 0xc3 ,
458
+ 0x85 , 0x24 , 0x5f , 0xe0 , 0x54 , 0xe3 , 0xdd , 0x5a ,
459
+ 0x97 , 0xa5 , 0xf5 , 0x76 , 0xfe , 0x06 , 0x40 , 0x25 ,
460
+ 0xd3 , 0xce , 0x04 , 0x2c , 0x56 , 0x6a , 0xb2 , 0xc5 ,
461
+ 0x07 , 0xb1 , 0x38 , 0xdb , 0x85 , 0x3e , 0x3d , 0x69 ,
462
+ 0x59 , 0x66 , 0x09 , 0x96 , 0x54 , 0x6c , 0xc9 , 0xc4 ,
463
+ 0xa6 , 0xea , 0xfd , 0xc7 , 0x77 , 0xc0 , 0x40 , 0xd7 ,
464
+ 0x0e , 0xaf , 0x46 , 0xf7 , 0x6d , 0xad , 0x39 , 0x79 ,
465
+ 0xe5 , 0xc5 , 0x36 , 0x0c , 0x33 , 0x17 , 0x16 , 0x6a ,
466
+ 0x1c , 0x89 , 0x4c , 0x94 , 0xa3 , 0x71 , 0x87 , 0x6a ,
467
+ 0x94 , 0xdf , 0x76 , 0x28 , 0xfe , 0x4e , 0xaa , 0xf2 ,
468
+ 0xcc , 0xb2 , 0x7d , 0x5a , 0xaa , 0xe0 , 0xad , 0x7a ,
469
+ 0xd0 , 0xf9 , 0xd4 , 0xb6 , 0xad , 0x3b , 0x54 , 0x09 ,
470
+ 0x87 , 0x46 , 0xd4 , 0x52 , 0x4d , 0x38 , 0x40 , 0x7a ,
471
+ 0x6d , 0xeb , 0x3a , 0xb7 , 0x8f , 0xab , 0x78 , 0xc9 ,
472
+ ) ,
473
+ } ,
474
+ ) ;
475
+
476
+ for tv in test_vectors. iter ( ) {
477
+ let mut c = ChaCha20 :: new ( & tv. key , & tv. nonce ) ;
478
+ let input: Vec < u8 > = repeat ( 0 ) . take ( tv. keystream . len ( ) ) . collect ( ) ;
479
+ let mut output: Vec < u8 > = repeat ( 0 ) . take ( input. len ( ) ) . collect ( ) ;
480
+ c. process ( & input[ ] , & mut output[ ] ) ;
481
+ assert_eq ! ( output, tv. keystream) ;
482
+ }
483
+ }
337
484
}
338
485
339
486
#[ cfg( test) ]
0 commit comments