]> Joshua Wise's Git repositories - dumload.git/blame - src/com/jcraft/jsch/DHGEX.java
Initial commit.
[dumload.git] / src / com / jcraft / jsch / DHGEX.java
CommitLineData
0763e16d
JW
1/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
2/*
3Copyright (c) 2002-2010 ymnk, JCraft,Inc. All rights reserved.
4
5Redistribution and use in source and binary forms, with or without
6modification, are permitted provided that the following conditions are met:
7
8 1. Redistributions of source code must retain the above copyright notice,
9 this list of conditions and the following disclaimer.
10
11 2. Redistributions in binary form must reproduce the above copyright
12 notice, this list of conditions and the following disclaimer in
13 the documentation and/or other materials provided with the distribution.
14
15 3. The names of the authors may not be used to endorse or promote products
16 derived from this software without specific prior written permission.
17
18THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
19INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
21INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
22INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
24OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
27EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*/
29
30package com.jcraft.jsch;
31
32public class DHGEX extends KeyExchange{
33
34 private static final int SSH_MSG_KEX_DH_GEX_GROUP= 31;
35 private static final int SSH_MSG_KEX_DH_GEX_INIT= 32;
36 private static final int SSH_MSG_KEX_DH_GEX_REPLY= 33;
37 private static final int SSH_MSG_KEX_DH_GEX_REQUEST= 34;
38
39 static int min=1024;
40
41// static int min=512;
42 static int preferred=1024;
43 static int max=1024;
44
45// static int preferred=1024;
46// static int max=2000;
47
48 static final int RSA=0;
49 static final int DSS=1;
50 private int type=0;
51
52 private int state;
53
54// com.jcraft.jsch.DH dh;
55 DH dh;
56
57 byte[] V_S;
58 byte[] V_C;
59 byte[] I_S;
60 byte[] I_C;
61
62 private Buffer buf;
63 private Packet packet;
64
65 private byte[] p;
66 private byte[] g;
67 private byte[] e;
68 //private byte[] f;
69
70 public void init(Session session,
71 byte[] V_S, byte[] V_C, byte[] I_S, byte[] I_C) throws Exception{
72 this.session=session;
73 this.V_S=V_S;
74 this.V_C=V_C;
75 this.I_S=I_S;
76 this.I_C=I_C;
77
78 try{
79 Class c=Class.forName(session.getConfig("sha-1"));
80 sha=(HASH)(c.newInstance());
81 sha.init();
82 }
83 catch(Exception e){
84 System.err.println(e);
85 }
86
87 buf=new Buffer();
88 packet=new Packet(buf);
89
90 try{
91 Class c=Class.forName(session.getConfig("dh"));
92 dh=(com.jcraft.jsch.DH)(c.newInstance());
93 dh.init();
94 }
95 catch(Exception e){
96// System.err.println(e);
97 throw e;
98 }
99
100 packet.reset();
101 buf.putByte((byte)SSH_MSG_KEX_DH_GEX_REQUEST);
102 buf.putInt(min);
103 buf.putInt(preferred);
104 buf.putInt(max);
105 session.write(packet);
106
107 if(JSch.getLogger().isEnabled(Logger.INFO)){
108 JSch.getLogger().log(Logger.INFO,
109 "SSH_MSG_KEX_DH_GEX_REQUEST("+min+"<"+preferred+"<"+max+") sent");
110 JSch.getLogger().log(Logger.INFO,
111 "expecting SSH_MSG_KEX_DH_GEX_GROUP");
112 }
113
114 state=SSH_MSG_KEX_DH_GEX_GROUP;
115 }
116
117 public boolean next(Buffer _buf) throws Exception{
118 int i,j;
119 switch(state){
120 case SSH_MSG_KEX_DH_GEX_GROUP:
121 // byte SSH_MSG_KEX_DH_GEX_GROUP(31)
122 // mpint p, safe prime
123 // mpint g, generator for subgroup in GF (p)
124 _buf.getInt();
125 _buf.getByte();
126 j=_buf.getByte();
127 if(j!=SSH_MSG_KEX_DH_GEX_GROUP){
128 System.err.println("type: must be SSH_MSG_KEX_DH_GEX_GROUP "+j);
129 return false;
130 }
131
132 p=_buf.getMPInt();
133 g=_buf.getMPInt();
134 /*
135for(int iii=0; iii<p.length; iii++){
136System.err.println("0x"+Integer.toHexString(p[iii]&0xff)+",");
137}
138System.err.println("");
139for(int iii=0; iii<g.length; iii++){
140System.err.println("0x"+Integer.toHexString(g[iii]&0xff)+",");
141}
142 */
143 dh.setP(p);
144 dh.setG(g);
145
146 // The client responds with:
147 // byte SSH_MSG_KEX_DH_GEX_INIT(32)
148 // mpint e <- g^x mod p
149 // x is a random number (1 < x < (p-1)/2)
150
151 e=dh.getE();
152
153 packet.reset();
154 buf.putByte((byte)SSH_MSG_KEX_DH_GEX_INIT);
155 buf.putMPInt(e);
156 session.write(packet);
157
158 if(JSch.getLogger().isEnabled(Logger.INFO)){
159 JSch.getLogger().log(Logger.INFO,
160 "SSH_MSG_KEX_DH_GEX_INIT sent");
161 JSch.getLogger().log(Logger.INFO,
162 "expecting SSH_MSG_KEX_DH_GEX_REPLY");
163 }
164
165 state=SSH_MSG_KEX_DH_GEX_REPLY;
166 return true;
167 //break;
168
169 case SSH_MSG_KEX_DH_GEX_REPLY:
170 // The server responds with:
171 // byte SSH_MSG_KEX_DH_GEX_REPLY(33)
172 // string server public host key and certificates (K_S)
173 // mpint f
174 // string signature of H
175 j=_buf.getInt();
176 j=_buf.getByte();
177 j=_buf.getByte();
178 if(j!=SSH_MSG_KEX_DH_GEX_REPLY){
179 System.err.println("type: must be SSH_MSG_KEX_DH_GEX_REPLY "+j);
180 return false;
181 }
182
183 K_S=_buf.getString();
184 // K_S is server_key_blob, which includes ....
185 // string ssh-dss
186 // impint p of dsa
187 // impint q of dsa
188 // impint g of dsa
189 // impint pub_key of dsa
190 //System.err.print("K_S: "); dump(K_S, 0, K_S.length);
191
192 byte[] f=_buf.getMPInt();
193 byte[] sig_of_H=_buf.getString();
194
195 dh.setF(f);
196 K=dh.getK();
197
198 //The hash H is computed as the HASH hash of the concatenation of the
199 //following:
200 // string V_C, the client's version string (CR and NL excluded)
201 // string V_S, the server's version string (CR and NL excluded)
202 // string I_C, the payload of the client's SSH_MSG_KEXINIT
203 // string I_S, the payload of the server's SSH_MSG_KEXINIT
204 // string K_S, the host key
205 // uint32 min, minimal size in bits of an acceptable group
206 // uint32 n, preferred size in bits of the group the server should send
207 // uint32 max, maximal size in bits of an acceptable group
208 // mpint p, safe prime
209 // mpint g, generator for subgroup
210 // mpint e, exchange value sent by the client
211 // mpint f, exchange value sent by the server
212 // mpint K, the shared secret
213 // This value is called the exchange hash, and it is used to authenti-
214 // cate the key exchange.
215
216 buf.reset();
217 buf.putString(V_C); buf.putString(V_S);
218 buf.putString(I_C); buf.putString(I_S);
219 buf.putString(K_S);
220 buf.putInt(min); buf.putInt(preferred); buf.putInt(max);
221 buf.putMPInt(p); buf.putMPInt(g); buf.putMPInt(e); buf.putMPInt(f);
222 buf.putMPInt(K);
223
224 byte[] foo=new byte[buf.getLength()];
225 buf.getByte(foo);
226 sha.update(foo, 0, foo.length);
227
228 H=sha.digest();
229
230 // System.err.print("H -> "); dump(H, 0, H.length);
231
232 i=0;
233 j=0;
234 j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
235 ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
236 String alg=Util.byte2str(K_S, i, j);
237 i+=j;
238
239 boolean result=false;
240 if(alg.equals("ssh-rsa")){
241 byte[] tmp;
242 byte[] ee;
243 byte[] n;
244
245 type=RSA;
246
247 j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
248 ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
249 tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
250 ee=tmp;
251 j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
252 ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
253 tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
254 n=tmp;
255
256// SignatureRSA sig=new SignatureRSA();
257// sig.init();
258
259 SignatureRSA sig=null;
260 try{
261 Class c=Class.forName(session.getConfig("signature.rsa"));
262 sig=(SignatureRSA)(c.newInstance());
263 sig.init();
264 }
265 catch(Exception e){
266 System.err.println(e);
267 }
268
269 sig.setPubKey(ee, n);
270 sig.update(H);
271 result=sig.verify(sig_of_H);
272
273 if(JSch.getLogger().isEnabled(Logger.INFO)){
274 JSch.getLogger().log(Logger.INFO,
275 "ssh_rsa_verify: signature "+result);
276 }
277
278 }
279 else if(alg.equals("ssh-dss")){
280 byte[] q=null;
281 byte[] tmp;
282
283 type=DSS;
284
285 j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
286 ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
287 tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
288 p=tmp;
289 j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
290 ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
291 tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
292 q=tmp;
293 j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
294 ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
295 tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
296 g=tmp;
297 j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
298 ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
299 tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
300 f=tmp;
301
302// SignatureDSA sig=new SignatureDSA();
303// sig.init();
304
305 SignatureDSA sig=null;
306 try{
307 Class c=Class.forName(session.getConfig("signature.dss"));
308 sig=(SignatureDSA)(c.newInstance());
309 sig.init();
310 }
311 catch(Exception e){
312 System.err.println(e);
313 }
314
315 sig.setPubKey(f, p, q, g);
316 sig.update(H);
317 result=sig.verify(sig_of_H);
318
319 if(JSch.getLogger().isEnabled(Logger.INFO)){
320 JSch.getLogger().log(Logger.INFO,
321 "ssh_dss_verify: signature "+result);
322 }
323
324 }
325 else{
326 System.err.println("unknown alg");
327 }
328 state=STATE_END;
329 return result;
330 }
331 return false;
332 }
333
334 public String getKeyType(){
335 if(type==DSS) return "DSA";
336 return "RSA";
337 }
338
339 public int getState(){return state; }
340}
This page took 0.048862 seconds and 4 git commands to generate.