aboutsummaryrefslogtreecommitdiffstats
path: root/lib/ssh/src/ssh_transport.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ssh/src/ssh_transport.erl')
-rw-r--r--lib/ssh/src/ssh_transport.erl83
1 files changed, 48 insertions, 35 deletions
diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl
index 2299346a30..eaab13433a 100644
--- a/lib/ssh/src/ssh_transport.erl
+++ b/lib/ssh/src/ssh_transport.erl
@@ -1328,13 +1328,15 @@ verify(PlainText, HashAlg, Sig, Key, _) ->
%%% Start of a more parameterized crypto handling.
cipher('AEAD_AES_128_GCM') ->
- #cipher{key_bytes = 16,
+ #cipher{impl = aes_128_gcm,
+ key_bytes = 16,
iv_bytes = 12,
block_bytes = 16,
pkt_type = aead};
cipher('AEAD_AES_256_GCM') ->
- #cipher{key_bytes = 32,
+ #cipher{impl = aes_256_gcm,
+ key_bytes = 32,
iv_bytes = 12,
block_bytes = 16,
pkt_type = aead};
@@ -1346,7 +1348,7 @@ cipher('3des-cbc') ->
block_bytes = 8};
cipher('aes128-cbc') ->
- #cipher{impl = aes_cbc,
+ #cipher{impl = aes_128_cbc,
key_bytes = 16,
iv_bytes = 16,
block_bytes = 16};
@@ -1370,7 +1372,8 @@ cipher('aes256-ctr') ->
block_bytes = 16};
cipher('[email protected]') -> % FIXME: Verify!!
- #cipher{key_bytes = 32,
+ #cipher{impl = chacha20_poly1305,
+ key_bytes = 32,
iv_bytes = 12,
block_bytes = 8,
pkt_type = aead};
@@ -1407,12 +1410,14 @@ encrypt_init(#ssh{encrypt = '[email protected]', role = Role} = Ssh)
encrypt_init(#ssh{encrypt = SshCipher, role = Role} = Ssh) when SshCipher == 'AEAD_AES_128_GCM';
SshCipher == 'AEAD_AES_256_GCM' ->
{IvMagic, KeyMagic} = encrypt_magic(Role),
- #cipher{key_bytes = KeyBytes,
+ #cipher{impl = CryptoCipher,
+ key_bytes = KeyBytes,
iv_bytes = IvBytes,
block_bytes = BlockBytes} = cipher(SshCipher),
IV = hash(Ssh, IvMagic, 8*IvBytes),
K = hash(Ssh, KeyMagic, 8*KeyBytes),
- {ok, Ssh#ssh{encrypt_keys = K,
+ {ok, Ssh#ssh{encrypt_cipher = CryptoCipher,
+ encrypt_keys = K,
encrypt_block_size = BlockBytes,
encrypt_ctx = IV}};
@@ -1425,11 +1430,12 @@ encrypt_init(#ssh{encrypt = SshCipher, role = Role} = Ssh) ->
IV = hash(Ssh, IvMagic, 8*IvBytes),
K = hash(Ssh, KeyMagic, 8*KeyBytes),
Ctx0 = crypto:crypto_init(CryptoCipher, K, IV, true),
- {ok, Ssh#ssh{encrypt_block_size = BlockBytes,
+ {ok, Ssh#ssh{encrypt_cipher = CryptoCipher,
+ encrypt_block_size = BlockBytes,
encrypt_ctx = Ctx0}}.
encrypt_final(Ssh) ->
- {ok, Ssh#ssh{encrypt = none,
+ {ok, Ssh#ssh{encrypt = none,
encrypt_keys = undefined,
encrypt_block_size = 8,
encrypt_ctx = undefined
@@ -1457,18 +1463,19 @@ encrypt(#ssh{encrypt = '[email protected]',
{Ssh, {EncBytes,Ctag}};
encrypt(#ssh{encrypt = SshCipher,
+ encrypt_cipher = CryptoCipher,
encrypt_keys = K,
encrypt_ctx = IV0} = Ssh,
<<LenData:4/binary, PayloadData/binary>>) when SshCipher == 'AEAD_AES_128_GCM' ;
SshCipher == 'AEAD_AES_256_GCM' ->
- {Ctext,Ctag} = crypto:block_encrypt(aes_gcm, K, IV0, {LenData,PayloadData}),
+ {Ctext,Ctag} = crypto:crypto_one_time_aead(CryptoCipher, K, IV0, PayloadData, LenData, true),
IV = next_gcm_iv(IV0),
{Ssh#ssh{encrypt_ctx = IV}, {<<LenData/binary,Ctext/binary>>,Ctag}};
encrypt(#ssh{encrypt_ctx = Ctx0} = Ssh, Data) ->
Enc = crypto:crypto_update(Ctx0, Data),
{Ssh, Enc}.
-
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Decryption
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -1485,12 +1492,14 @@ decrypt_init(#ssh{decrypt = '[email protected]', role = Role} = Ssh)
decrypt_init(#ssh{decrypt = SshCipher, role = Role} = Ssh) when SshCipher == 'AEAD_AES_128_GCM';
SshCipher == 'AEAD_AES_256_GCM' ->
{IvMagic, KeyMagic} = decrypt_magic(Role),
- #cipher{key_bytes = KeyBytes,
+ #cipher{impl = CryptoCipher,
+ key_bytes = KeyBytes,
iv_bytes = IvBytes,
block_bytes = BlockBytes} = cipher(SshCipher),
IV = hash(Ssh, IvMagic, 8*IvBytes),
K = hash(Ssh, KeyMagic, 8*KeyBytes),
- {ok, Ssh#ssh{decrypt_keys = K,
+ {ok, Ssh#ssh{decrypt_cipher = CryptoCipher,
+ decrypt_keys = K,
decrypt_block_size = BlockBytes,
decrypt_ctx = IV}};
@@ -1503,9 +1512,11 @@ decrypt_init(#ssh{decrypt = SshCipher, role = Role} = Ssh) ->
IV = hash(Ssh, IvMagic, 8*IvBytes),
K = hash(Ssh, KeyMagic, 8*KeyBytes),
Ctx0 = crypto:crypto_init(CryptoCipher, K, IV, false),
- {ok, Ssh#ssh{decrypt_block_size = BlockBytes,
+ {ok, Ssh#ssh{decrypt_cipher = CryptoCipher,
+ decrypt_block_size = BlockBytes,
decrypt_ctx = Ctx0}}.
+
decrypt_final(Ssh) ->
{ok, Ssh#ssh {decrypt = none,
decrypt_keys = undefined,
@@ -1517,35 +1528,37 @@ decrypt(Ssh, <<>>) ->
{Ssh, <<>>};
decrypt(#ssh{decrypt = '[email protected]',
- decrypt_keys = {K1,_K2},
- recv_sequence = Seq} = Ssh, {length,EncryptedLen}) ->
- PacketLenBin = crypto:crypto_one_time(chacha20, K1, <<0:8/unit:8, Seq:8/unit:8>>, EncryptedLen, false),
- {Ssh, PacketLenBin};
-
-decrypt(#ssh{decrypt = '[email protected]',
- decrypt_keys = {_K1,K2},
- recv_sequence = Seq} = Ssh, {AAD,Ctext,Ctag}) ->
- %% The length is already decoded and used to divide the input
- %% Check the mac (important that it is timing-safe):
- PolyKey = crypto:crypto_one_time(chacha20, K2, <<0:8/unit:8,Seq:8/unit:8>>, <<0:32/unit:8>>, false),
- case equal_const_time(Ctag, crypto:poly1305(PolyKey, <<AAD/binary,Ctext/binary>>)) of
- true ->
- %% MAC is ok, decode
- IV2 = <<1:8/little-unit:8, Seq:8/unit:8>>,
- PlainText = crypto:crypto_one_time(chacha20, K2, IV2, Ctext, false),
- {Ssh, PlainText};
- false ->
- {Ssh,error}
+ decrypt_keys = {K1,K2},
+ recv_sequence = Seq} = Ssh, Data) ->
+ case Data of
+ {length,EncryptedLen} ->
+ %% The length is decrypted separately in a first step
+ PacketLenBin = crypto:crypto_one_time(chacha20, K1, <<0:8/unit:8, Seq:8/unit:8>>, EncryptedLen, false),
+ {Ssh, PacketLenBin};
+ {AAD,Ctext,Ctag} ->
+ %% The length is already decrypted and used to divide the input
+ %% Check the mac (important that it is timing-safe):
+ PolyKey = crypto:crypto_one_time(chacha20, K2, <<0:8/unit:8,Seq:8/unit:8>>, <<0:32/unit:8>>, false),
+ case equal_const_time(Ctag, crypto:poly1305(PolyKey, <<AAD/binary,Ctext/binary>>)) of
+ true ->
+ %% MAC is ok, decode
+ IV2 = <<1:8/little-unit:8, Seq:8/unit:8>>,
+ PlainText = crypto:crypto_one_time(chacha20, K2, IV2, Ctext, false),
+ {Ssh, PlainText};
+ false ->
+ {Ssh,error}
+ end
end;
decrypt(#ssh{decrypt = none} = Ssh, Data) ->
{Ssh, Data};
decrypt(#ssh{decrypt = SshCipher,
+ decrypt_cipher = CryptoCipher,
decrypt_keys = K,
- decrypt_ctx = IV0} = Ssh, Data = {_AAD,_Ctext,_Ctag}) when SshCipher == 'AEAD_AES_128_GCM' ;
- SshCipher == 'AEAD_AES_256_GCM' ->
- Dec = crypto:block_decrypt(aes_gcm, K, IV0, Data), % Dec = PlainText | error
+ decrypt_ctx = IV0} = Ssh, {AAD,Ctext,Ctag}) when SshCipher == 'AEAD_AES_128_GCM' ;
+ SshCipher == 'AEAD_AES_256_GCM' ->
+ Dec = crypto:crypto_one_time_aead(CryptoCipher, K, IV0, Ctext, AAD, Ctag, false),
IV = next_gcm_iv(IV0),
{Ssh#ssh{decrypt_ctx = IV}, Dec};