001: /* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
002: /*
003: Copyright (c) 2002-2008 ymnk, JCraft,Inc. All rights reserved.
004:
005: Redistribution and use in source and binary forms, with or without
006: modification, are permitted provided that the following conditions are met:
007:
008: 1. Redistributions of source code must retain the above copyright notice,
009: this list of conditions and the following disclaimer.
010:
011: 2. Redistributions in binary form must reproduce the above copyright
012: notice, this list of conditions and the following disclaimer in
013: the documentation and/or other materials provided with the distribution.
014:
015: 3. The names of the authors may not be used to endorse or promote products
016: derived from this software without specific prior written permission.
017:
018: THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
019: INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
020: FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
021: INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
022: INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
023: LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
024: OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
025: LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
026: NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
027: EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
028: */
029:
030: package com.jcraft.jsch;
031:
032: public class DHG1 extends KeyExchange {
033:
034: static final byte[] g = { 2 };
035: static final byte[] p = { (byte) 0x00, (byte) 0xFF, (byte) 0xFF,
036: (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
037: (byte) 0xFF, (byte) 0xFF, (byte) 0xC9, (byte) 0x0F,
038: (byte) 0xDA, (byte) 0xA2, (byte) 0x21, (byte) 0x68,
039: (byte) 0xC2, (byte) 0x34, (byte) 0xC4, (byte) 0xC6,
040: (byte) 0x62, (byte) 0x8B, (byte) 0x80, (byte) 0xDC,
041: (byte) 0x1C, (byte) 0xD1, (byte) 0x29, (byte) 0x02,
042: (byte) 0x4E, (byte) 0x08, (byte) 0x8A, (byte) 0x67,
043: (byte) 0xCC, (byte) 0x74, (byte) 0x02, (byte) 0x0B,
044: (byte) 0xBE, (byte) 0xA6, (byte) 0x3B, (byte) 0x13,
045: (byte) 0x9B, (byte) 0x22, (byte) 0x51, (byte) 0x4A,
046: (byte) 0x08, (byte) 0x79, (byte) 0x8E, (byte) 0x34,
047: (byte) 0x04, (byte) 0xDD, (byte) 0xEF, (byte) 0x95,
048: (byte) 0x19, (byte) 0xB3, (byte) 0xCD, (byte) 0x3A,
049: (byte) 0x43, (byte) 0x1B, (byte) 0x30, (byte) 0x2B,
050: (byte) 0x0A, (byte) 0x6D, (byte) 0xF2, (byte) 0x5F,
051: (byte) 0x14, (byte) 0x37, (byte) 0x4F, (byte) 0xE1,
052: (byte) 0x35, (byte) 0x6D, (byte) 0x6D, (byte) 0x51,
053: (byte) 0xC2, (byte) 0x45, (byte) 0xE4, (byte) 0x85,
054: (byte) 0xB5, (byte) 0x76, (byte) 0x62, (byte) 0x5E,
055: (byte) 0x7E, (byte) 0xC6, (byte) 0xF4, (byte) 0x4C,
056: (byte) 0x42, (byte) 0xE9, (byte) 0xA6, (byte) 0x37,
057: (byte) 0xED, (byte) 0x6B, (byte) 0x0B, (byte) 0xFF,
058: (byte) 0x5C, (byte) 0xB6, (byte) 0xF4, (byte) 0x06,
059: (byte) 0xB7, (byte) 0xED, (byte) 0xEE, (byte) 0x38,
060: (byte) 0x6B, (byte) 0xFB, (byte) 0x5A, (byte) 0x89,
061: (byte) 0x9F, (byte) 0xA5, (byte) 0xAE, (byte) 0x9F,
062: (byte) 0x24, (byte) 0x11, (byte) 0x7C, (byte) 0x4B,
063: (byte) 0x1F, (byte) 0xE6, (byte) 0x49, (byte) 0x28,
064: (byte) 0x66, (byte) 0x51, (byte) 0xEC, (byte) 0xE6,
065: (byte) 0x53, (byte) 0x81, (byte) 0xFF, (byte) 0xFF,
066: (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
067: (byte) 0xFF, (byte) 0xFF };
068:
069: private static final int SSH_MSG_KEXDH_INIT = 30;
070: private static final int SSH_MSG_KEXDH_REPLY = 31;
071:
072: static final int RSA = 0;
073: static final int DSS = 1;
074: private int type = 0;
075:
076: private int state;
077:
078: DH dh;
079: // HASH sha;
080:
081: // byte[] K;
082: // byte[] H;
083:
084: byte[] V_S;
085: byte[] V_C;
086: byte[] I_S;
087: byte[] I_C;
088:
089: // byte[] K_S;
090:
091: byte[] e;
092:
093: private Buffer buf;
094: private Packet packet;
095:
096: public void init(Session session, byte[] V_S, byte[] V_C,
097: byte[] I_S, byte[] I_C) throws Exception {
098: this .session = session;
099: this .V_S = V_S;
100: this .V_C = V_C;
101: this .I_S = I_S;
102: this .I_C = I_C;
103:
104: // sha=new SHA1();
105: // sha.init();
106: try {
107: Class c = Class.forName(session.getConfig("sha-1"));
108: sha = (HASH) (c.newInstance());
109: sha.init();
110: } catch (Exception e) {
111: System.err.println(e);
112: }
113:
114: buf = new Buffer();
115: packet = new Packet(buf);
116:
117: try {
118: Class c = Class.forName(session.getConfig("dh"));
119: dh = (DH) (c.newInstance());
120: dh.init();
121: } catch (Exception e) {
122: //System.err.println(e);
123: throw e;
124: }
125:
126: dh.setP(p);
127: dh.setG(g);
128:
129: // The client responds with:
130: // byte SSH_MSG_KEXDH_INIT(30)
131: // mpint e <- g^x mod p
132: // x is a random number (1 < x < (p-1)/2)
133:
134: e = dh.getE();
135:
136: packet.reset();
137: buf.putByte((byte) SSH_MSG_KEXDH_INIT);
138: buf.putMPInt(e);
139: session.write(packet);
140:
141: if (JSch.getLogger().isEnabled(Logger.INFO)) {
142: JSch.getLogger()
143: .log(Logger.INFO, "SSH_MSG_KEXDH_INIT sent");
144: JSch.getLogger().log(Logger.INFO,
145: "expecting SSH_MSG_KEXDH_REPLY");
146: }
147:
148: state = SSH_MSG_KEXDH_REPLY;
149: }
150:
151: public boolean next(Buffer _buf) throws Exception {
152: int i, j;
153:
154: switch (state) {
155: case SSH_MSG_KEXDH_REPLY:
156: // The server responds with:
157: // byte SSH_MSG_KEXDH_REPLY(31)
158: // string server public host key and certificates (K_S)
159: // mpint f
160: // string signature of H
161: j = _buf.getInt();
162: j = _buf.getByte();
163: j = _buf.getByte();
164: if (j != 31) {
165: System.err.println("type: must be 31 " + j);
166: return false;
167: }
168:
169: K_S = _buf.getString();
170: // K_S is server_key_blob, which includes ....
171: // string ssh-dss
172: // impint p of dsa
173: // impint q of dsa
174: // impint g of dsa
175: // impint pub_key of dsa
176: //System.err.print("K_S: "); //dump(K_S, 0, K_S.length);
177: byte[] f = _buf.getMPInt();
178: byte[] sig_of_H = _buf.getString();
179: /*
180: for(int ii=0; ii<sig_of_H.length;ii++){
181: System.err.print(Integer.toHexString(sig_of_H[ii]&0xff));
182: System.err.print(": ");
183: }
184: System.err.println("");
185: */
186:
187: dh.setF(f);
188: K = dh.getK();
189:
190: //The hash H is computed as the HASH hash of the concatenation of the
191: //following:
192: // string V_C, the client's version string (CR and NL excluded)
193: // string V_S, the server's version string (CR and NL excluded)
194: // string I_C, the payload of the client's SSH_MSG_KEXINIT
195: // string I_S, the payload of the server's SSH_MSG_KEXINIT
196: // string K_S, the host key
197: // mpint e, exchange value sent by the client
198: // mpint f, exchange value sent by the server
199: // mpint K, the shared secret
200: // This value is called the exchange hash, and it is used to authenti-
201: // cate the key exchange.
202: buf.reset();
203: buf.putString(V_C);
204: buf.putString(V_S);
205: buf.putString(I_C);
206: buf.putString(I_S);
207: buf.putString(K_S);
208: buf.putMPInt(e);
209: buf.putMPInt(f);
210: buf.putMPInt(K);
211: byte[] foo = new byte[buf.getLength()];
212: buf.getByte(foo);
213: sha.update(foo, 0, foo.length);
214: H = sha.digest();
215: //System.err.print("H -> "); //dump(H, 0, H.length);
216:
217: i = 0;
218: j = 0;
219: j = ((K_S[i++] << 24) & 0xff000000)
220: | ((K_S[i++] << 16) & 0x00ff0000)
221: | ((K_S[i++] << 8) & 0x0000ff00)
222: | ((K_S[i++]) & 0x000000ff);
223: String alg = new String(K_S, i, j);
224: i += j;
225:
226: boolean result = false;
227:
228: if (alg.equals("ssh-rsa")) {
229: byte[] tmp;
230: byte[] ee;
231: byte[] n;
232:
233: type = RSA;
234:
235: j = ((K_S[i++] << 24) & 0xff000000)
236: | ((K_S[i++] << 16) & 0x00ff0000)
237: | ((K_S[i++] << 8) & 0x0000ff00)
238: | ((K_S[i++]) & 0x000000ff);
239: tmp = new byte[j];
240: System.arraycopy(K_S, i, tmp, 0, j);
241: i += j;
242: ee = tmp;
243: j = ((K_S[i++] << 24) & 0xff000000)
244: | ((K_S[i++] << 16) & 0x00ff0000)
245: | ((K_S[i++] << 8) & 0x0000ff00)
246: | ((K_S[i++]) & 0x000000ff);
247: tmp = new byte[j];
248: System.arraycopy(K_S, i, tmp, 0, j);
249: i += j;
250: n = tmp;
251:
252: // SignatureRSA sig=new SignatureRSA();
253: // sig.init();
254:
255: SignatureRSA sig = null;
256: try {
257: Class c = Class.forName(session
258: .getConfig("signature.rsa"));
259: sig = (SignatureRSA) (c.newInstance());
260: sig.init();
261: } catch (Exception e) {
262: System.err.println(e);
263: }
264:
265: sig.setPubKey(ee, n);
266: sig.update(H);
267: result = sig.verify(sig_of_H);
268:
269: if (JSch.getLogger().isEnabled(Logger.INFO)) {
270: JSch.getLogger().log(Logger.INFO,
271: "ssh_rsa_verify: signature " + result);
272: }
273:
274: } else if (alg.equals("ssh-dss")) {
275: byte[] q = null;
276: byte[] tmp;
277: byte[] p;
278: byte[] g;
279:
280: type = DSS;
281:
282: j = ((K_S[i++] << 24) & 0xff000000)
283: | ((K_S[i++] << 16) & 0x00ff0000)
284: | ((K_S[i++] << 8) & 0x0000ff00)
285: | ((K_S[i++]) & 0x000000ff);
286: tmp = new byte[j];
287: System.arraycopy(K_S, i, tmp, 0, j);
288: i += j;
289: p = tmp;
290: j = ((K_S[i++] << 24) & 0xff000000)
291: | ((K_S[i++] << 16) & 0x00ff0000)
292: | ((K_S[i++] << 8) & 0x0000ff00)
293: | ((K_S[i++]) & 0x000000ff);
294: tmp = new byte[j];
295: System.arraycopy(K_S, i, tmp, 0, j);
296: i += j;
297: q = tmp;
298: j = ((K_S[i++] << 24) & 0xff000000)
299: | ((K_S[i++] << 16) & 0x00ff0000)
300: | ((K_S[i++] << 8) & 0x0000ff00)
301: | ((K_S[i++]) & 0x000000ff);
302: tmp = new byte[j];
303: System.arraycopy(K_S, i, tmp, 0, j);
304: i += j;
305: g = tmp;
306: j = ((K_S[i++] << 24) & 0xff000000)
307: | ((K_S[i++] << 16) & 0x00ff0000)
308: | ((K_S[i++] << 8) & 0x0000ff00)
309: | ((K_S[i++]) & 0x000000ff);
310: tmp = new byte[j];
311: System.arraycopy(K_S, i, tmp, 0, j);
312: i += j;
313: f = tmp;
314: // SignatureDSA sig=new SignatureDSA();
315: // sig.init();
316: SignatureDSA sig = null;
317: try {
318: Class c = Class.forName(session
319: .getConfig("signature.dss"));
320: sig = (SignatureDSA) (c.newInstance());
321: sig.init();
322: } catch (Exception e) {
323: System.err.println(e);
324: }
325: sig.setPubKey(f, p, q, g);
326: sig.update(H);
327: result = sig.verify(sig_of_H);
328:
329: if (JSch.getLogger().isEnabled(Logger.INFO)) {
330: JSch.getLogger().log(Logger.INFO,
331: "ssh_dss_verify: signature " + result);
332: }
333:
334: } else {
335: System.err.println("unknown alg");
336: }
337: state = STATE_END;
338: return result;
339: }
340: return false;
341: }
342:
343: public String getKeyType() {
344: if (type == DSS)
345: return "DSA";
346: return "RSA";
347: }
348:
349: public int getState() {
350: return state;
351: }
352: }
|