Skip to content

Commit dd654d8

Browse files
committed
Merge branch 'master' into 3.0.0
2 parents bb9ac20 + 362758d commit dd654d8

1 file changed

Lines changed: 41 additions & 0 deletions

File tree

sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/generic/SignatureEd25519.java

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@
1818
*/
1919
package org.apache.sshd.common.util.security.eddsa.generic;
2020

21+
import java.security.SignatureException;
2122
import java.util.Map;
23+
import java.util.Objects;
2224

2325
import org.apache.sshd.common.keyprovider.KeyPairProvider;
2426
import org.apache.sshd.common.session.SessionContext;
@@ -33,6 +35,15 @@
3335
*/
3436
public class SignatureEd25519 extends AbstractSignature {
3537

38+
// See https://www.rfc-editor.org/rfc/rfc7748.html#section-4.1
39+
// 2^252 + 0x14def9dea2f79cd65812631a5cf5d3ed; little-endian
40+
private static final int[] ED25519_ORDER = { //
41+
0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, //
42+
0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, //
43+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
44+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10 //
45+
};
46+
3647
public SignatureEd25519() {
3748
super(SecurityUtils.ED25519, KeyPairProvider.SSH_ED25519);
3849
}
@@ -49,4 +60,34 @@ public boolean verify(SessionContext session, byte[] sig) throws Exception {
4960

5061
return doVerify(data);
5162
}
63+
64+
@Override
65+
protected boolean doVerify(byte[] data) throws SignatureException {
66+
java.security.Signature verifier = Objects.requireNonNull(getSignature(), "Signature not initialized");
67+
if (SecurityUtils.EDDSA.equals(verifier.getProvider().getName())) {
68+
// Fix CVE 2020-36843 in net.i2p.crypto.eddsa 0.3.0: check that s is in the range [0 .. L), where
69+
// L is the order.
70+
//
71+
// Note: Wikipedia says 0 < S < L. https://en.wikipedia.org/w/index.php?title=EdDSA&oldid=1304068429
72+
// RFC 8032 says 0 <= S < L. https://datatracker.ietf.org/doc/html/rfc8032#section-5.1.7
73+
//
74+
// We stick to RFC 8032 here.
75+
if (data.length != 64 || !isValidFactor(data)) {
76+
return false;
77+
}
78+
}
79+
return verifier.verify(data);
80+
}
81+
82+
private static boolean isValidFactor(byte[] sig) {
83+
// Must be strictly smaller than the field order (little-endian).
84+
for (int i = 31; i >= 0; i--) {
85+
int y = (sig[i + 32] & 0xFF) - ED25519_ORDER[i];
86+
if (y != 0) {
87+
return y < 0;
88+
}
89+
}
90+
return false;
91+
}
92+
5293
}

0 commit comments

Comments
 (0)