-
Notifications
You must be signed in to change notification settings - Fork 144
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for
[email protected]
KEX algorithm.
- Loading branch information
1 parent
f955209
commit fa68dc9
Showing
16 changed files
with
615 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
/* | ||
* Copyright (c) 2015-2018 ymnk, JCraft,Inc. All rights reserved. | ||
* | ||
* Redistribution and use in source and binary forms, with or without modification, are permitted | ||
* provided that the following conditions are met: | ||
* | ||
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions | ||
* and the following disclaimer. | ||
* | ||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of | ||
* conditions and the following disclaimer in the documentation and/or other materials provided with | ||
* the distribution. | ||
* | ||
* 3. The names of the authors may not be used to endorse or promote products derived from this | ||
* software without specific prior written permission. | ||
* | ||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
* DISCLAIMED. IN NO EVENT SHALL JCRAFT, INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY | ||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR | ||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
*/ | ||
|
||
package com.jcraft.jsch; | ||
|
||
class DH25519SNTRUP761 extends DHXECKEM { | ||
public DH25519SNTRUP761() { | ||
kem_name = "sntrup761"; | ||
sha_name = "sha-512"; | ||
curve_name = "X25519"; | ||
encapsulation_len = 1039; | ||
key_len = 32; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,223 @@ | ||
/* | ||
* Copyright (c) 2015-2018 ymnk, JCraft,Inc. All rights reserved. | ||
* | ||
* Redistribution and use in source and binary forms, with or without modification, are permitted | ||
* provided that the following conditions are met: | ||
* | ||
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions | ||
* and the following disclaimer. | ||
* | ||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of | ||
* conditions and the following disclaimer in the documentation and/or other materials provided with | ||
* the distribution. | ||
* | ||
* 3. The names of the authors may not be used to endorse or promote products derived from this | ||
* software without specific prior written permission. | ||
* | ||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
* DISCLAIMED. IN NO EVENT SHALL JCRAFT, INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY | ||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR | ||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
*/ | ||
|
||
package com.jcraft.jsch; | ||
|
||
abstract class DHXECKEM extends KeyExchange { | ||
|
||
private static final int SSH_MSG_KEX_ECDH_INIT = 30; | ||
private static final int SSH_MSG_KEX_ECDH_REPLY = 31; | ||
private int state; | ||
|
||
byte[] Q_C; | ||
|
||
byte[] V_S; | ||
byte[] V_C; | ||
byte[] I_S; | ||
byte[] I_C; | ||
|
||
byte[] e; | ||
|
||
private Buffer buf; | ||
private Packet packet; | ||
|
||
private KEM kem; | ||
private XDH xdh; | ||
|
||
protected String kem_name; | ||
protected String sha_name; | ||
protected String curve_name; | ||
protected int encapsulation_len; | ||
protected int key_len; | ||
|
||
@Override | ||
public void init(Session session, byte[] V_S, byte[] V_C, byte[] I_S, byte[] I_C) | ||
throws Exception { | ||
this.V_S = V_S; | ||
this.V_C = V_C; | ||
this.I_S = I_S; | ||
this.I_C = I_C; | ||
|
||
try { | ||
Class<? extends HASH> c = Class.forName(session.getConfig(sha_name)).asSubclass(HASH.class); | ||
sha = c.getDeclaredConstructor().newInstance(); | ||
sha.init(); | ||
} catch (Exception e) { | ||
throw new JSchException(e.toString(), e); | ||
} | ||
|
||
buf = new Buffer(); | ||
packet = new Packet(buf); | ||
|
||
packet.reset(); | ||
buf.putByte((byte) SSH_MSG_KEX_ECDH_INIT); | ||
|
||
try { | ||
Class<? extends KEM> k = Class.forName(session.getConfig(kem_name)).asSubclass(KEM.class); | ||
kem = k.getDeclaredConstructor().newInstance(); | ||
kem.init(); | ||
|
||
Class<? extends XDH> c = Class.forName(session.getConfig("xdh")).asSubclass(XDH.class); | ||
xdh = c.getDeclaredConstructor().newInstance(); | ||
xdh.init(curve_name, key_len); | ||
|
||
byte[] kem_public_key_C = kem.getPublicKey(); | ||
byte[] xec_public_key_C = xdh.getQ(); | ||
Q_C = new byte[kem_public_key_C.length + xec_public_key_C.length]; | ||
System.arraycopy(kem_public_key_C, 0, Q_C, 0, kem_public_key_C.length); | ||
System.arraycopy(xec_public_key_C, 0, Q_C, kem_public_key_C.length, xec_public_key_C.length); | ||
buf.putString(Q_C); | ||
} catch (Exception | NoClassDefFoundError e) { | ||
throw new JSchException(e.toString(), e); | ||
} | ||
|
||
if (V_S == null) { // This is a really ugly hack for Session.checkKexes ;-( | ||
return; | ||
} | ||
|
||
session.write(packet); | ||
|
||
if (session.getLogger().isEnabled(Logger.INFO)) { | ||
session.getLogger().log(Logger.INFO, "SSH_MSG_KEX_ECDH_INIT sent"); | ||
session.getLogger().log(Logger.INFO, "expecting SSH_MSG_KEX_ECDH_REPLY"); | ||
} | ||
|
||
state = SSH_MSG_KEX_ECDH_REPLY; | ||
} | ||
|
||
@Override | ||
public boolean next(Buffer _buf) throws Exception { | ||
int i, j; | ||
switch (state) { | ||
case SSH_MSG_KEX_ECDH_REPLY: | ||
// The server responds with: | ||
// byte SSH_MSG_KEX_ECDH_REPLY | ||
// string K_S, server's public host key | ||
// string Q_S, server's ephemeral public key octet string | ||
// string the signature on the exchange hash | ||
j = _buf.getInt(); | ||
j = _buf.getByte(); | ||
j = _buf.getByte(); | ||
if (j != SSH_MSG_KEX_ECDH_REPLY) { | ||
if (session.getLogger().isEnabled(Logger.ERROR)) { | ||
session.getLogger().log(Logger.ERROR, "type: must be SSH_MSG_KEX_ECDH_REPLY " + j); | ||
} | ||
return false; | ||
} | ||
|
||
K_S = _buf.getString(); | ||
|
||
byte[] Q_S = _buf.getString(); | ||
if (Q_S.length != encapsulation_len + key_len) { | ||
return false; | ||
} | ||
|
||
byte[] encapsulation = new byte[encapsulation_len]; | ||
byte[] xec_public_key_S = new byte[key_len]; | ||
System.arraycopy(Q_S, 0, encapsulation, 0, encapsulation_len); | ||
System.arraycopy(Q_S, encapsulation_len, xec_public_key_S, 0, key_len); | ||
|
||
// RFC 5656, | ||
// 4. ECDH Key Exchange | ||
// All elliptic curve public keys MUST be validated after they are | ||
// received. An example of a validation algorithm can be found in | ||
// Section 3.2.2 of [SEC1]. If a key fails validation, | ||
// the key exchange MUST fail. | ||
if (!xdh.validate(xec_public_key_S)) { | ||
return false; | ||
} | ||
|
||
byte[] tmp = kem.decapsulate(encapsulation); | ||
sha.update(tmp, 0, tmp.length); | ||
tmp = xdh.getSecret(xec_public_key_S); | ||
tmp = normalize(tmp); | ||
sha.update(tmp, 0, tmp.length); | ||
K = sha.digest(); | ||
|
||
byte[] sig_of_H = _buf.getString(); | ||
|
||
// The hash H is computed as the HASH hash of the concatenation of the | ||
// following: | ||
// string V_C, client's identification string (CR and LF excluded) | ||
// string V_S, server's identification string (CR and LF excluded) | ||
// string I_C, payload of the client's SSH_MSG_KEXINIT | ||
// string I_S, payload of the server's SSH_MSG_KEXINIT | ||
// string K_S, server's public host key | ||
// string Q_C, client's ephemeral public key octet string | ||
// string Q_S, server's ephemeral public key octet string | ||
// string K, shared secret | ||
|
||
// draft-josefsson-ntruprime-ssh-02, | ||
// 3. Key Exchange Method: sntrup761x25519-sha512 | ||
// ... | ||
// The SSH_MSG_KEX_ECDH_REPLY's signature value is computed as described | ||
// in [RFC5656] with the following changes. Instead of encoding the | ||
// shared secret K as 'mpint', it MUST be encoded as 'string'. The | ||
// shared secret K value MUST be the 64-byte output octet string of the | ||
// SHA-512 hash computed with the input as the 32-byte octet string key | ||
// output from the key encapsulation mechanism of sntrup761 concatenated | ||
// with the 32-byte octet string of X25519(a, X25519(b, 9)) = X25519(b, | ||
// X25519(a, 9)). | ||
buf.reset(); | ||
buf.putString(V_C); | ||
buf.putString(V_S); | ||
buf.putString(I_C); | ||
buf.putString(I_S); | ||
buf.putString(K_S); | ||
buf.putString(Q_C); | ||
buf.putString(Q_S); | ||
putK(buf); | ||
byte[] foo = new byte[buf.getLength()]; | ||
buf.getByte(foo); | ||
|
||
sha.update(foo, 0, foo.length); | ||
H = sha.digest(); | ||
|
||
i = 0; | ||
j = 0; | ||
j = ((K_S[i++] << 24) & 0xff000000) | ((K_S[i++] << 16) & 0x00ff0000) | ||
| ((K_S[i++] << 8) & 0x0000ff00) | ((K_S[i++]) & 0x000000ff); | ||
String alg = Util.byte2str(K_S, i, j); | ||
i += j; | ||
|
||
boolean result = verify(alg, K_S, i, sig_of_H); | ||
|
||
state = STATE_END; | ||
return result; | ||
} | ||
return false; | ||
} | ||
|
||
@Override | ||
public int getState() { | ||
return state; | ||
} | ||
|
||
@Override | ||
void putK(Buffer b) { | ||
b.putString(K); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -103,6 +103,9 @@ public class JSch { | |
config.put("curve25519-sha256", "com.jcraft.jsch.DH25519"); | ||
config.put("[email protected]", "com.jcraft.jsch.DH25519"); | ||
config.put("curve448-sha512", "com.jcraft.jsch.DH448"); | ||
config.put("[email protected]", "com.jcraft.jsch.DH25519SNTRUP761"); | ||
|
||
config.put("sntrup761", "com.jcraft.jsch.bc.SNTRUP761"); | ||
|
||
config.put("dh", "com.jcraft.jsch.jce.DH"); | ||
config.put("3des-cbc", "com.jcraft.jsch.jce.TripleDESCBC"); | ||
|
@@ -239,7 +242,7 @@ public class JSch { | |
Util.getSystemProperty("jsch.check_ciphers", "[email protected]")); | ||
config.put("CheckMacs", Util.getSystemProperty("jsch.check_macs", "")); | ||
config.put("CheckKexes", Util.getSystemProperty("jsch.check_kexes", | ||
"curve25519-sha256,[email protected],curve448-sha512")); | ||
"[email protected],curve25519-sha256,[email protected],curve448-sha512")); | ||
config.put("CheckSignatures", | ||
Util.getSystemProperty("jsch.check_signatures", "ssh-ed25519,ssh-ed448")); | ||
config.put("FingerprintHash", Util.getSystemProperty("jsch.fingerprint_hash", "sha256")); | ||
|
Oops, something went wrong.