1818 */
1919package org .apache .sshd .common .util .security .eddsa .generic ;
2020
21+ import java .security .SignatureException ;
2122import java .util .Map ;
23+ import java .util .Objects ;
2224
2325import org .apache .sshd .common .keyprovider .KeyPairProvider ;
2426import org .apache .sshd .common .session .SessionContext ;
3335 */
3436public 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