]> Joshua Wise's Git repositories - dumload.git/blob - src/com/jcraft/jsch/DHGEX.java
Initial commit.
[dumload.git] / src / com / jcraft / jsch / DHGEX.java
1 /* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
2 /*
3 Copyright (c) 2002-2010 ymnk, JCraft,Inc. All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, 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
18 THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
19 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
21 INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
22 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
24 OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
27 EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 package com.jcraft.jsch;
31
32 public 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       /*
135 for(int iii=0; iii<p.length; iii++){
136 System.err.println("0x"+Integer.toHexString(p[iii]&0xff)+",");
137 }
138 System.err.println("");
139 for(int iii=0; iii<g.length; iii++){
140 System.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.039962 seconds and 4 git commands to generate.