Skip to content

Commit

Permalink
Merge pull request #705 from norrisjeremy/20241108
Browse files Browse the repository at this point in the history
0.2.22 changes
  • Loading branch information
mwiede authored Nov 11, 2024
2 parents c6593cd + f393a84 commit 900b781
Show file tree
Hide file tree
Showing 18 changed files with 530 additions and 38 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/maven.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
java: ['8', '11', '17', '21', '22']
java: ['8', '11', '17', '21', '23']
steps:
- name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
Expand Down
10 changes: 8 additions & 2 deletions ChangeLog.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
* [0.2.22](https://github.com/mwiede/jsch/releases/tag/jsch-0.2.22)
* Add support for sntrup761x25519-sha512 KEX algorithm.
* Add support for mlkem768x25519-sha256, mlkem768nistp256-sha256 & mlkem1024nistp384-sha384 KEX algorithms.
* [0.2.21](https://github.com/mwiede/jsch/releases/tag/jsch-0.2.21)
* [#692](https://github.com/mwiede/jsch/pull/692) Update Deflate.java by @mjmst74.
* [0.2.20](https://github.com/mwiede/jsch/releases/tag/jsch-0.2.20)
* [#529](https://github.com/mwiede/jsch/pull/529) Update `Hostkey.getFingerprint()` method to output more moden format first introduced with OpenSSH 6.8.
* [#622](https://github.com/mwiede/jsch/pull/622) Add stack trace to log message when an exception occurs during authentication.
* [#649](https://github.com/mwiede/jsch/pull/649) Incorrect Oid for service name in GSSAPI authentication.
* [0.2.19](https://github.com/mwiede/jsch/releases/tag/jsch-0.2.19)
* Enforce DHGEX prime modulus bit length meets configured constraints.
* #604 Fix possible rekeying timeouts.
* [#604](https://github.com/mwiede/jsch/issues/604) Fix possible rekeying timeouts.
* [0.2.18](https://github.com/mwiede/jsch/releases/tag/jsch-0.2.18)
* Handle negated patterns according to ssh_config(5) by @bmiddaugh in https://github.com/mwiede/jsch/pull/565
* [#565](https://github.com/mwiede/jsch/pull/565) Handle negated patterns according to ssh_config(5) by @bmiddaugh.
* [0.2.17](https://github.com/mwiede/jsch/releases/tag/jsch-0.2.17)
* Add PBKDF2-HMAC-SHA512/256 & PBKDF2-HMAC-SHA512/224, which are both supported as of Java 21.
* [0.2.16](https://github.com/mwiede/jsch/releases/tag/jsch-0.2.16)
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,7 @@
Import-Package: \
com.sun.jna*;version="${range;[=0,+)}";resolution:=optional,\
org.apache.logging.log4j*;version="${range;[=0,4)}";resolution:=optional,\
org.bouncycastle*;version="[1.76,${versionmask;+})";resolution:=optional,\
org.bouncycastle*;version="[1.79,${versionmask;+})";resolution:=optional,\
org.slf4j*;version="[1.7,${versionmask;+})";resolution:=optional,\
org.newsclub.net.unix;resolution:=optional,\
org.ietf.jgss;resolution:=optional,\
Expand Down
38 changes: 38 additions & 0 deletions src/main/java/com/jcraft/jsch/DH25519MLKEM768.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* 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 DH25519MLKEM768 extends DHXECKEM {
public DH25519MLKEM768() {
kem_name = "mlkem768";
sha_name = "sha-256";
curve_name = "X25519";
kem_pubkey_len = 1184;
kem_encap_len = 1088;
xec_key_len = 32;
}
}
38 changes: 38 additions & 0 deletions src/main/java/com/jcraft/jsch/DHEC256MLKEM768.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* 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 DHEC256MLKEM768 extends DHECNKEM {
public DHEC256MLKEM768() {
kem_name = "mlkem768";
sha_name = "sha-256";
kem_pubkey_len = 1184;
kem_encap_len = 1088;
ecdh_key_size = 256;
ecdh_key_len = 65;
}
}
38 changes: 38 additions & 0 deletions src/main/java/com/jcraft/jsch/DHEC384MLKEM1024.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* 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 DHEC384MLKEM1024 extends DHECNKEM {
public DHEC384MLKEM1024() {
kem_name = "mlkem1024";
sha_name = "sha-384";
kem_pubkey_len = 1568;
kem_encap_len = 1568;
ecdh_key_size = 384;
ecdh_key_len = 97;
}
}
233 changes: 233 additions & 0 deletions src/main/java/com/jcraft/jsch/DHECNKEM.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,233 @@
/*
* 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 DHECNKEM extends KeyExchange {

private static final int SSH_MSG_KEX_HYBRID_INIT = 30;
private static final int SSH_MSG_KEX_HYBRID_REPLY = 31;
private int state;

byte[] C_INIT;

byte[] V_S;
byte[] V_C;
byte[] I_S;
byte[] I_C;

byte[] e;

private Buffer buf;
private Packet packet;

private KEM kem;
private ECDH ecdh;

protected String kem_name;
protected String sha_name;
protected int kem_pubkey_len;
protected int kem_encap_len;
protected int ecdh_key_size;
protected int ecdh_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();
// command + string len + C_INIT len
buf.checkFreeSize(1 + 4 + kem_pubkey_len + ecdh_key_len);
buf.putByte((byte) SSH_MSG_KEX_HYBRID_INIT);

try {
Class<? extends KEM> k = Class.forName(session.getConfig(kem_name)).asSubclass(KEM.class);
kem = k.getDeclaredConstructor().newInstance();
kem.init();

Class<? extends ECDH> c =
Class.forName(session.getConfig("ecdh-sha2-nistp")).asSubclass(ECDH.class);
ecdh = c.getDeclaredConstructor().newInstance();
ecdh.init(ecdh_key_size);

byte[] kem_public_key_C = kem.getPublicKey();
byte[] ecdh_public_key_C = ecdh.getQ();
C_INIT = new byte[kem_pubkey_len + ecdh_key_len];
System.arraycopy(kem_public_key_C, 0, C_INIT, 0, kem_pubkey_len);
System.arraycopy(ecdh_public_key_C, 0, C_INIT, kem_pubkey_len, ecdh_key_len);
buf.putString(C_INIT);
} catch (Exception 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_HYBRID_INIT sent");
session.getLogger().log(Logger.INFO, "expecting SSH_MSG_KEX_HYBRID_REPLY");
}

state = SSH_MSG_KEX_HYBRID_REPLY;
}

@Override
public boolean next(Buffer _buf) throws Exception {
int i, j;
switch (state) {
case SSH_MSG_KEX_HYBRID_REPLY:
// The server responds with:
// byte SSH_MSG_KEX_HYBRID_REPLY
// string K_S, server's public host key
// string S_REPLY
// string the signature on the exchange hash
j = _buf.getInt();
j = _buf.getByte();
j = _buf.getByte();
if (j != SSH_MSG_KEX_HYBRID_REPLY) {
if (session.getLogger().isEnabled(Logger.ERROR)) {
session.getLogger().log(Logger.ERROR, "type: must be SSH_MSG_KEX_HYBRID_REPLY " + j);
}
return false;
}

K_S = _buf.getString();

byte[] S_REPLY = _buf.getString();
if (S_REPLY.length != kem_encap_len + ecdh_key_len) {
return false;
}

byte[] encapsulation = new byte[kem_encap_len];
byte[] ecdh_public_key_S = new byte[ecdh_key_len];
System.arraycopy(S_REPLY, 0, encapsulation, 0, kem_encap_len);
System.arraycopy(S_REPLY, kem_encap_len, ecdh_public_key_S, 0, ecdh_key_len);

byte[][] r_s = KeyPairECDSA.fromPoint(ecdh_public_key_S);

// 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 (!ecdh.validate(r_s[0], r_s[1])) {
return false;
}

byte[] tmp = null;
try {
tmp = kem.decapsulate(encapsulation);
sha.update(tmp, 0, tmp.length);
} finally {
Util.bzero(tmp);
}
try {
tmp = normalize(ecdh.getSecret(r_s[0], r_s[1]));
sha.update(tmp, 0, tmp.length);
} finally {
Util.bzero(tmp);
}
K = encodeAsString(sha.digest());

byte[] sig_of_H = _buf.getString();

// draft-kampanakis-curdle-ssh-pq-ke-04,
// 2.5. Key Derivation
//
// The PQ/T Hybrid key exchange hash H is the result of computing the
// HASH, where HASH is the hash algorithm specified in the named PQ/T
// Hybrid key exchange method name, over 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 C_INIT, client message octet string
// string S_REPLY, server message octet string
// string K, SSH shared secret
//
// K, the shared secret used in H, was traditionally encoded as an
// integer (mpint) as per [RFC4253], [RFC5656], and [RFC8731]. In this
// specification, K is the hash output of the two concatenated byte
// arrays (Section 2.4) which is not an integer. Thus, K is encoded as a
// string using the process described in Section 5 of [RFC4251] and is
// then fed along with other data in H to the key exchange method's HASH
// function to generate encryption keys.
buf.reset();
buf.putString(V_C);
buf.putString(V_S);
buf.putString(I_C);
buf.putString(I_S);
buf.putString(K_S);
buf.putString(C_INIT);
buf.putString(S_REPLY);
byte[] foo = new byte[buf.getLength()];
buf.getByte(foo);

sha.update(foo, 0, foo.length);
sha.update(K, 0, K.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;
}
}
Loading

0 comments on commit 900b781

Please sign in to comment.