1515
1616// http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.chacha20poly1305?annotate=HEAD
1717
18- use std:: convert:: TryInto ;
19-
20- use aes:: cipher:: { BlockSizeUser , StreamCipherSeek } ;
21- use byteorder:: { BigEndian , ByteOrder } ;
22- use chacha20:: cipher:: { KeyInit , KeyIvInit , StreamCipher } ;
23- use chacha20:: { ChaCha20Legacy , ChaCha20LegacyCore } ;
24- use generic_array:: typenum:: { Unsigned , U16 , U32 , U8 } ;
25- use generic_array:: GenericArray ;
26- use poly1305:: Poly1305 ;
27- use subtle:: ConstantTimeEq ;
18+ #[ cfg( feature = "aws-lc-rs" ) ]
19+ use aws_lc_rs:: aead:: chacha20_poly1305_openssh;
20+ #[ cfg( all( not( feature = "aws-lc-rs" ) , feature = "ring" ) ) ]
21+ use ring:: aead:: chacha20_poly1305_openssh;
2822
2923use super :: super :: Error ;
30- use crate :: cipher:: PACKET_LENGTH_LEN ;
3124use crate :: mac:: MacAlgorithm ;
3225
3326pub struct SshChacha20Poly1305Cipher { }
3427
35- type KeyLength = U32 ;
36- type NonceLength = U8 ;
37- type TagLength = U16 ;
38- type Key = GenericArray < u8 , KeyLength > ;
39- type Nonce = GenericArray < u8 , NonceLength > ;
40-
4128impl super :: Cipher for SshChacha20Poly1305Cipher {
4229 fn key_len ( & self ) -> usize {
43- KeyLength :: to_usize ( ) * 2
30+ chacha20_poly1305_openssh :: KEY_LEN
4431 }
4532
46- #[ allow( clippy:: indexing_slicing) ] // length checked
4733 fn make_opening_key (
4834 & self ,
4935 k : & [ u8 ] ,
5036 _: & [ u8 ] ,
5137 _: & [ u8 ] ,
5238 _: & dyn MacAlgorithm ,
5339 ) -> Box < dyn super :: OpeningKey + Send > {
54- let mut k1 = Key :: default ( ) ;
55- let mut k2 = Key :: default ( ) ;
56- k1. clone_from_slice ( & k[ KeyLength :: to_usize ( ) ..] ) ;
57- k2. clone_from_slice ( & k[ ..KeyLength :: to_usize ( ) ] ) ;
58- Box :: new ( OpeningKey { k1, k2 } )
40+ Box :: new ( OpeningKey ( chacha20_poly1305_openssh:: OpeningKey :: new (
41+ #[ allow( clippy:: unwrap_used) ]
42+ k. try_into ( ) . unwrap ( ) ,
43+ ) ) )
5944 }
6045
61- #[ allow( clippy:: indexing_slicing) ] // length checked
6246 fn make_sealing_key (
6347 & self ,
6448 k : & [ u8 ] ,
6549 _: & [ u8 ] ,
6650 _: & [ u8 ] ,
6751 _: & dyn MacAlgorithm ,
6852 ) -> Box < dyn super :: SealingKey + Send > {
69- let mut k1 = Key :: default ( ) ;
70- let mut k2 = Key :: default ( ) ;
71- k1. clone_from_slice ( & k[ KeyLength :: to_usize ( ) ..] ) ;
72- k2. clone_from_slice ( & k[ ..KeyLength :: to_usize ( ) ] ) ;
73- Box :: new ( SealingKey { k1, k2 } )
53+ Box :: new ( SealingKey ( chacha20_poly1305_openssh:: SealingKey :: new (
54+ #[ allow( clippy:: unwrap_used) ]
55+ k. try_into ( ) . unwrap ( ) ,
56+ ) ) )
7457 }
7558}
7659
77- pub struct OpeningKey {
78- k1 : Key ,
79- k2 : Key ,
80- }
81-
82- pub struct SealingKey {
83- k1 : Key ,
84- k2 : Key ,
85- }
60+ pub struct OpeningKey ( chacha20_poly1305_openssh:: OpeningKey ) ;
8661
87- #[ allow( clippy:: indexing_slicing) ] // length checked
88- fn make_counter ( sequence_number : u32 ) -> Nonce {
89- let mut nonce = Nonce :: default ( ) ;
90- let i0 = NonceLength :: to_usize ( ) - 4 ;
91- BigEndian :: write_u32 ( & mut nonce[ i0..] , sequence_number) ;
92- nonce
93- }
62+ pub struct SealingKey ( chacha20_poly1305_openssh:: SealingKey ) ;
9463
9564impl super :: OpeningKey for OpeningKey {
9665 fn decrypt_packet_length (
9766 & self ,
9867 sequence_number : u32 ,
9968 encrypted_packet_length : & [ u8 ] ,
10069 ) -> [ u8 ; 4 ] {
101- // Fine because of self.packet_length_to_read_for_block_length()
102- #[ allow( clippy:: unwrap_used, clippy:: indexing_slicing) ]
103- let mut encrypted_packet_length: [ u8 ; 4 ] = encrypted_packet_length. try_into ( ) . unwrap ( ) ;
104-
105- let nonce = make_counter ( sequence_number) ;
106- let mut cipher = ChaCha20Legacy :: new ( & self . k1 , & nonce) ;
107- cipher. apply_keystream ( & mut encrypted_packet_length) ;
108-
109- encrypted_packet_length
70+ self . 0 . decrypt_packet_length (
71+ sequence_number,
72+ #[ allow( clippy:: unwrap_used) ]
73+ encrypted_packet_length. try_into ( ) . unwrap ( ) ,
74+ )
11075 }
11176
11277 fn tag_len ( & self ) -> usize {
113- TagLength :: to_usize ( )
78+ chacha20_poly1305_openssh :: TAG_LEN
11479 }
11580
116- #[ allow( clippy:: indexing_slicing) ] // lengths checked
11781 fn open < ' a > (
11882 & mut self ,
11983 sequence_number : u32 ,
120- ciphertext_in_plaintext_out : & ' a mut [ u8 ] ,
121- tag : & [ u8 ] ,
84+ ciphertext_and_tag : & ' a mut [ u8 ] ,
12285 ) -> Result < & ' a [ u8 ] , Error > {
123- let nonce = make_counter ( sequence_number) ;
124- let expected_tag = compute_poly1305 ( & nonce, & self . k2 , ciphertext_in_plaintext_out) ;
125-
126- if !bool:: from ( expected_tag. ct_eq ( tag) ) {
127- return Err ( Error :: DecryptionError ) ;
128- }
129-
130- let mut cipher = ChaCha20Legacy :: new ( & self . k2 , & nonce) ;
131-
132- cipher. seek ( <ChaCha20LegacyCore as BlockSizeUser >:: BlockSize :: to_usize ( ) ) ;
133- cipher. apply_keystream ( & mut ciphertext_in_plaintext_out[ PACKET_LENGTH_LEN ..] ) ;
134-
135- Ok ( & ciphertext_in_plaintext_out[ PACKET_LENGTH_LEN ..] )
86+ let ciphertext_len = ciphertext_and_tag. len ( ) - self . tag_len ( ) ;
87+ let ( ciphertext_in_plaintext_out, tag) = ciphertext_and_tag. split_at_mut ( ciphertext_len) ;
88+
89+ self . 0
90+ . open_in_place (
91+ sequence_number,
92+ ciphertext_in_plaintext_out,
93+ #[ allow( clippy:: unwrap_used) ]
94+ & tag. try_into ( ) . unwrap ( ) ,
95+ )
96+ . map_err ( |_| Error :: DecryptionError )
13697 }
13798}
13899
@@ -163,7 +124,7 @@ impl super::SealingKey for SealingKey {
163124 }
164125
165126 fn tag_len ( & self ) -> usize {
166- TagLength :: to_usize ( )
127+ chacha20_poly1305_openssh :: TAG_LEN
167128 }
168129
169130 fn seal (
@@ -172,31 +133,11 @@ impl super::SealingKey for SealingKey {
172133 plaintext_in_ciphertext_out : & mut [ u8 ] ,
173134 tag : & mut [ u8 ] ,
174135 ) {
175- let nonce = make_counter ( sequence_number) ;
176-
177- let mut cipher = ChaCha20Legacy :: new ( & self . k1 , & nonce) ;
178- #[ allow( clippy:: indexing_slicing) ] // length checked
179- cipher. apply_keystream ( & mut plaintext_in_ciphertext_out[ ..PACKET_LENGTH_LEN ] ) ;
180-
181- // --
182- let mut cipher = ChaCha20Legacy :: new ( & self . k2 , & nonce) ;
183-
184- cipher. seek ( <ChaCha20LegacyCore as BlockSizeUser >:: BlockSize :: to_usize ( ) ) ;
185- #[ allow( clippy:: indexing_slicing, clippy:: unwrap_used) ]
186- cipher. apply_keystream ( & mut plaintext_in_ciphertext_out[ PACKET_LENGTH_LEN ..] ) ;
187-
188- // --
189-
190- tag. copy_from_slice (
191- compute_poly1305 ( & nonce, & self . k2 , plaintext_in_ciphertext_out) . as_slice ( ) ,
136+ self . 0 . seal_in_place (
137+ sequence_number,
138+ plaintext_in_ciphertext_out,
139+ #[ allow( clippy:: unwrap_used) ]
140+ tag. try_into ( ) . unwrap ( ) ,
192141 ) ;
193142 }
194143}
195-
196- fn compute_poly1305 ( nonce : & Nonce , key : & Key , data : & [ u8 ] ) -> poly1305:: Tag {
197- let mut cipher = ChaCha20Legacy :: new ( key, nonce) ;
198- let mut poly_key = GenericArray :: < u8 , U32 > :: default ( ) ;
199- cipher. apply_keystream ( & mut poly_key) ;
200-
201- Poly1305 :: new ( & poly_key) . compute_unpadded ( data)
202- }
0 commit comments