~ubuntu-branches/ubuntu/trusty/jsch/trusty-proposed

« back to all changes in this revision

Viewing changes to src/main/java/com/jcraft/jsch/DHGEX256.java

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2014-01-06 10:50:04 UTC
  • mfrom: (4.2.1 experimental) (6.1.2 sid)
  • Revision ID: package-import@ubuntu.com-20140106105004-9al5p968hmaaj78t
Tags: 0.1.50-1ubuntu1
* Resync with Debian unstable.
* Drop dependency on libjzlib-java for continued main inclusion. 

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
 
2
/*
 
3
Copyright (c) 2002-2012 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 DHGEX256 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-256"));
 
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=normalize(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
}