Develop and Download Open Source Software

Browse Subversion Repository

Contents of /trunk/ttssh2/ttxssh/kex.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 4378 - (hide annotations) (download) (as text)
Tue Mar 8 14:19:03 2011 UTC (2 years, 3 months ago) by maya
File MIME type: text/x-csrc
File size: 14573 byte(s)
SSH2 の 圧縮で none を利用できるように修正した。
ソース整理
  鍵形式・KEXプロトコル・MAC・圧縮の名前や関数を取得する関数を作成。
    これにより定義で順序を入れ替えてもよくなった。
  enum に型名を付けた。
  共通の関数を使えるところで使うようにした。
1 maya 4304 /*
2     Copyright (c) 2011, TeraTerm Project
3     All rights reserved.
4    
5     Redistribution and use in source and binary forms, with or without modification,
6     are permitted provided that the following conditions are met:
7    
8     Redistributions of source code must retain the above copyright notice, this list of
9     conditions and the following disclaimer.
10    
11     Redistributions in binary form must reproduce the above copyright notice, this list
12     of conditions and the following disclaimer in the documentation and/or other materials
13     provided with the distribution.
14    
15     The name of Robert O'Callahan may not be used to endorse or promote products derived from
16     this software without specific prior written permission.
17    
18     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
19     ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20     OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21     THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22     EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23     SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25     OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26     SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27     */
28    
29     #include "ttxssh.h"
30     #include "kex.h"
31    
32     extern Newkeys current_keys[MODE_MAX];
33    
34     static DH *dh_new_group_asc(const char *gen, const char *modulus)
35     {
36     DH *dh = NULL;
37    
38     if ((dh = DH_new()) == NULL) {
39     printf("dh_new_group_asc: DH_new");
40     goto error;
41     }
42    
43     // PとGは公開してもよい素数の組み合わせ
44     if (BN_hex2bn(&dh->p, modulus) == 0) {
45     printf("BN_hex2bn p");
46     goto error;
47     }
48    
49     if (BN_hex2bn(&dh->g, gen) == 0) {
50     printf("BN_hex2bn g");
51     goto error;
52     }
53    
54     return (dh);
55    
56     error:
57     DH_free(dh);
58     return (NULL);
59     }
60    
61    
62     DH *dh_new_group1(void)
63     {
64     static char *gen = "2", *group1 =
65     "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1"
66     "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD"
67     "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245"
68     "E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED"
69     "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE65381"
70     "FFFFFFFF" "FFFFFFFF";
71    
72     return (dh_new_group_asc(gen, group1));
73     }
74    
75    
76     DH *dh_new_group14(void)
77     {
78     static char *gen = "2", *group14 =
79     "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1"
80     "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD"
81     "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245"
82     "E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED"
83     "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE45B3D"
84     "C2007CB8" "A163BF05" "98DA4836" "1C55D39A" "69163FA8" "FD24CF5F"
85     "83655D23" "DCA3AD96" "1C62F356" "208552BB" "9ED52907" "7096966D"
86     "670C354E" "4ABC9804" "F1746C08" "CA18217C" "32905E46" "2E36CE3B"
87     "E39E772C" "180E8603" "9B2783A2" "EC07A28F" "B5C55DF0" "6F4C52C9"
88     "DE2BCBF6" "95581718" "3995497C" "EA956AE5" "15D22618" "98FA0510"
89     "15728E5A" "8AACAA68" "FFFFFFFF" "FFFFFFFF";
90    
91     return (dh_new_group_asc(gen, group14));
92     }
93    
94    
95     // DH鍵を生成する
96     void dh_gen_key(PTInstVar pvar, DH *dh, int we_need /* bytes */ )
97     {
98     int i;
99    
100     dh->priv_key = NULL;
101    
102     // 秘密にすべき乱数(X)を生成
103     for (i = 0 ; i < 10 ; i++) { // retry counter
104     if (dh->priv_key != NULL) {
105     BN_clear_free(dh->priv_key);
106     }
107     dh->priv_key = BN_new();
108     if (dh->priv_key == NULL)
109     goto error;
110     if (BN_rand(dh->priv_key, 2*(we_need*8), 0, 0) == 0)
111     goto error;
112     if (DH_generate_key(dh) == 0)
113     goto error;
114     if (dh_pub_is_valid(dh, dh->pub_key))
115     break;
116     }
117     if (i >= 10) {
118     goto error;
119     }
120     return;
121    
122     error:;
123     notify_fatal_error(pvar, "error occurred @ dh_gen_key()");
124    
125     }
126    
127    
128     int dh_estimate(int bits)
129     {
130     if (bits <= 128)
131     return (1024); /* O(2**86) */
132     if (bits <= 192)
133     return (2048); /* O(2**116) */
134     return (4096); /* O(2**156) */
135     }
136    
137    
138     // SHA-1(160bit)を求める
139     unsigned char *kex_dh_hash(char *client_version_string,
140     char *server_version_string,
141     char *ckexinit, int ckexinitlen,
142     char *skexinit, int skexinitlen,
143     u_char *serverhostkeyblob, int sbloblen,
144     BIGNUM *client_dh_pub,
145     BIGNUM *server_dh_pub,
146 maya 4305 BIGNUM *shared_secret,
147     unsigned int *hashlen)
148 maya 4304 {
149     buffer_t *b;
150     static unsigned char digest[EVP_MAX_MD_SIZE];
151     const EVP_MD *evp_md = EVP_sha1();
152     EVP_MD_CTX md;
153    
154     b = buffer_init();
155     buffer_put_string(b, client_version_string, strlen(client_version_string));
156     buffer_put_string(b, server_version_string, strlen(server_version_string));
157    
158     /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */
159     buffer_put_int(b, ckexinitlen+1);
160     buffer_put_char(b, SSH2_MSG_KEXINIT);
161     buffer_append(b, ckexinit, ckexinitlen);
162     buffer_put_int(b, skexinitlen+1);
163     buffer_put_char(b, SSH2_MSG_KEXINIT);
164     buffer_append(b, skexinit, skexinitlen);
165    
166     buffer_put_string(b, serverhostkeyblob, sbloblen);
167     buffer_put_bignum2(b, client_dh_pub);
168     buffer_put_bignum2(b, server_dh_pub);
169     buffer_put_bignum2(b, shared_secret);
170    
171     // yutaka
172     //debug_print(38, buffer_ptr(b), buffer_len(b));
173    
174     EVP_DigestInit(&md, evp_md);
175     EVP_DigestUpdate(&md, buffer_ptr(b), buffer_len(b));
176     EVP_DigestFinal(&md, digest, NULL);
177    
178     buffer_free(b);
179    
180     //write_buffer_file(digest, EVP_MD_size(evp_md));
181    
182 maya 4305 *hashlen = EVP_MD_size(evp_md);
183    
184 maya 4304 return digest;
185     }
186    
187    
188     // SHA-1(160bit)/SHA-256(256bit)を求める
189 maya 4305 unsigned char *kex_dh_gex_hash(const EVP_MD *evp_md,
190     char *client_version_string,
191 maya 4304 char *server_version_string,
192     char *ckexinit, int ckexinitlen,
193     char *skexinit, int skexinitlen,
194     u_char *serverhostkeyblob, int sbloblen,
195     int kexgex_min,
196     int kexgex_bits,
197     int kexgex_max,
198     BIGNUM *kexgex_p,
199     BIGNUM *kexgex_g,
200     BIGNUM *client_dh_pub,
201     BIGNUM *server_dh_pub,
202 maya 4305 BIGNUM *shared_secret,
203     unsigned int *hashlen)
204 maya 4304 {
205     buffer_t *b;
206     static unsigned char digest[EVP_MAX_MD_SIZE];
207     EVP_MD_CTX md;
208    
209     b = buffer_init();
210     buffer_put_string(b, client_version_string, strlen(client_version_string));
211     buffer_put_string(b, server_version_string, strlen(server_version_string));
212    
213     /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */
214     buffer_put_int(b, ckexinitlen+1);
215     buffer_put_char(b, SSH2_MSG_KEXINIT);
216     buffer_append(b, ckexinit, ckexinitlen);
217     buffer_put_int(b, skexinitlen+1);
218     buffer_put_char(b, SSH2_MSG_KEXINIT);
219     buffer_append(b, skexinit, skexinitlen);
220    
221     buffer_put_string(b, serverhostkeyblob, sbloblen);
222    
223     // DH group sizeのビット数を加算する
224     buffer_put_int(b, kexgex_min);
225     buffer_put_int(b, kexgex_bits);
226     buffer_put_int(b, kexgex_max);
227    
228     // DH鍵の素数と生成元を加算する
229     buffer_put_bignum2(b, kexgex_p);
230     buffer_put_bignum2(b, kexgex_g);
231    
232     buffer_put_bignum2(b, client_dh_pub);
233     buffer_put_bignum2(b, server_dh_pub);
234     buffer_put_bignum2(b, shared_secret);
235    
236     // yutaka
237     //debug_print(38, buffer_ptr(b), buffer_len(b));
238    
239     EVP_DigestInit(&md, evp_md);
240     EVP_DigestUpdate(&md, buffer_ptr(b), buffer_len(b));
241     EVP_DigestFinal(&md, digest, NULL);
242    
243     buffer_free(b);
244    
245     //write_buffer_file(digest, EVP_MD_size(evp_md));
246    
247 maya 4305 *hashlen = EVP_MD_size(evp_md);
248    
249 maya 4304 return digest;
250     }
251    
252    
253 maya 4314 unsigned char *kex_ecdh_hash(const EVP_MD *evp_md,
254     const EC_GROUP *ec_group,
255     char *client_version_string,
256     char *server_version_string,
257     char *ckexinit, int ckexinitlen,
258     char *skexinit, int skexinitlen,
259     u_char *serverhostkeyblob, int sbloblen,
260     const EC_POINT *client_dh_pub,
261     const EC_POINT *server_dh_pub,
262     BIGNUM *shared_secret,
263     unsigned int *hashlen)
264     {
265     buffer_t *b;
266     static unsigned char digest[EVP_MAX_MD_SIZE];
267     EVP_MD_CTX md;
268    
269     b = buffer_init();
270     buffer_put_string(b, client_version_string, strlen(client_version_string));
271     buffer_put_string(b, server_version_string, strlen(server_version_string));
272    
273     /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */
274     buffer_put_int(b, ckexinitlen+1);
275     buffer_put_char(b, SSH2_MSG_KEXINIT);
276     buffer_append(b, ckexinit, ckexinitlen);
277     buffer_put_int(b, skexinitlen+1);
278     buffer_put_char(b, SSH2_MSG_KEXINIT);
279     buffer_append(b, skexinit, skexinitlen);
280    
281     buffer_put_string(b, serverhostkeyblob, sbloblen);
282    
283     buffer_put_ecpoint(b, ec_group, client_dh_pub);
284     buffer_put_ecpoint(b, ec_group, server_dh_pub);
285     buffer_put_bignum2(b, shared_secret);
286    
287     // yutaka
288     //debug_print(38, buffer_ptr(b), buffer_len(b));
289    
290     EVP_DigestInit(&md, evp_md);
291     EVP_DigestUpdate(&md, buffer_ptr(b), buffer_len(b));
292     EVP_DigestFinal(&md, digest, NULL);
293    
294     buffer_free(b);
295    
296     //write_buffer_file(digest, EVP_MD_size(evp_md));
297    
298     *hashlen = EVP_MD_size(evp_md);
299    
300     return digest;
301     }
302    
303    
304 maya 4304 int dh_pub_is_valid(DH *dh, BIGNUM *dh_pub)
305     {
306     int i;
307     int n = BN_num_bits(dh_pub);
308     int bits_set = 0;
309    
310     if (dh_pub->neg) {
311     //logit("invalid public DH value: negativ");
312     return 0;
313     }
314     for (i = 0; i <= n; i++)
315     if (BN_is_bit_set(dh_pub, i))
316     bits_set++;
317     //debug2("bits set: %d/%d", bits_set, BN_num_bits(dh->p));
318    
319     /* if g==2 and bits_set==1 then computing log_g(dh_pub) is trivial */
320     if (bits_set > 1 && (BN_cmp(dh_pub, dh->p) == -1))
321     return 1;
322     //logit("invalid public DH value (%d/%d)", bits_set, BN_num_bits(dh->p));
323     return 0;
324     }
325    
326    
327 maya 4314 // from openssh 5.8p1 key.c
328     int key_ec_validate_public(const EC_GROUP *group, const EC_POINT *public)
329     {
330     BN_CTX *bnctx;
331     EC_POINT *nq = NULL;
332     BIGNUM *order, *x, *y, *tmp;
333     int ret = -1;
334    
335     if ((bnctx = BN_CTX_new()) == NULL) {
336     return ret;
337     }
338     BN_CTX_start(bnctx);
339    
340     /*
341     * We shouldn't ever hit this case because bignum_get_ecpoint()
342     * refuses to load GF2m points.
343     */
344     if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) !=
345     NID_X9_62_prime_field) {
346     goto out;
347     }
348    
349     /* Q != infinity */
350     if (EC_POINT_is_at_infinity(group, public)) {
351     goto out;
352     }
353    
354     if ((x = BN_CTX_get(bnctx)) == NULL ||
355     (y = BN_CTX_get(bnctx)) == NULL ||
356     (order = BN_CTX_get(bnctx)) == NULL ||
357     (tmp = BN_CTX_get(bnctx)) == NULL) {
358     goto out;
359     }
360    
361     /* log2(x) > log2(order)/2, log2(y) > log2(order)/2 */
362     if (EC_GROUP_get_order(group, order, bnctx) != 1) {
363     goto out;
364     }
365     if (EC_POINT_get_affine_coordinates_GFp(group, public,
366     x, y, bnctx) != 1) {
367     goto out;
368     }
369     if (BN_num_bits(x) <= BN_num_bits(order) / 2) {
370     goto out;
371     }
372     if (BN_num_bits(y) <= BN_num_bits(order) / 2) {
373     goto out;
374     }
375    
376     /* nQ == infinity (n == order of subgroup) */
377     if ((nq = EC_POINT_new(group)) == NULL) {
378     goto out;
379     }
380     if (EC_POINT_mul(group, nq, NULL, public, order, bnctx) != 1) {
381     goto out;
382     }
383     if (EC_POINT_is_at_infinity(group, nq) != 1) {
384     goto out;
385     }
386    
387     /* x < order - 1, y < order - 1 */
388     if (!BN_sub(tmp, order, BN_value_one())) {
389     goto out;
390     }
391     if (BN_cmp(x, tmp) >= 0) {
392     goto out;
393     }
394     if (BN_cmp(y, tmp) >= 0) {
395     goto out;
396     }
397     ret = 0;
398     out:
399     BN_CTX_free(bnctx);
400     EC_POINT_free(nq);
401     return ret;
402     }
403    
404    
405 maya 4304 static u_char *derive_key(int id, int need, u_char *hash, BIGNUM *shared_secret,
406     char *session_id, int session_id_len,
407 maya 4305 const EVP_MD *evp_md)
408 maya 4304 {
409     buffer_t *b;
410     EVP_MD_CTX md;
411     char c = id;
412     int have;
413     int mdsz = EVP_MD_size(evp_md);
414     u_char *digest = malloc(roundup(need, mdsz));
415    
416     if (digest == NULL)
417     goto skip;
418    
419     b = buffer_init();
420     if (b == NULL)
421     goto skip;
422    
423     buffer_put_bignum2(b, shared_secret);
424    
425     /* K1 = HASH(K || H || "A" || session_id) */
426     EVP_DigestInit(&md, evp_md);
427     EVP_DigestUpdate(&md, buffer_ptr(b), buffer_len(b));
428     EVP_DigestUpdate(&md, hash, mdsz);
429     EVP_DigestUpdate(&md, &c, 1);
430     EVP_DigestUpdate(&md, session_id, session_id_len);
431     EVP_DigestFinal(&md, digest, NULL);
432    
433     /*
434     * expand key:
435     * Kn = HASH(K || H || K1 || K2 || ... || Kn-1)
436     * Key = K1 || K2 || ... || Kn
437     */
438     for (have = mdsz; need > have; have += mdsz) {
439     EVP_DigestInit(&md, evp_md);
440     EVP_DigestUpdate(&md, buffer_ptr(b), buffer_len(b));
441     EVP_DigestUpdate(&md, hash, mdsz);
442     EVP_DigestUpdate(&md, digest, have);
443     EVP_DigestFinal(&md, digest + have, NULL);
444     }
445     buffer_free(b);
446    
447     skip:;
448     return digest;
449     }
450    
451    
452     void kex_derive_keys(PTInstVar pvar, int need, u_char *hash, BIGNUM *shared_secret,
453     char *session_id, int session_id_len)
454     {
455     #define NKEYS 6
456     u_char *keys[NKEYS];
457     int i, mode, ctos;
458    
459     for (i = 0; i < NKEYS; i++) {
460 maya 4305 keys[i] = derive_key('A'+i, need, hash, shared_secret, session_id, session_id_len,
461 maya 4378 get_kex_algorithm_EVP_MD(pvar->kex_type));
462 maya 4304 //debug_print(i, keys[i], need);
463     }
464    
465     for (mode = 0; mode < MODE_MAX; mode++) {
466     if (mode == MODE_OUT)
467     ctos = 1;
468     else
469     ctos = 0;
470    
471     #if 0
472     // free already allocated buffer (2004.12.27 yutaka)
473     // キー再作成時にMAC corruptとなるので削除。(2005.1.5 yutaka)
474     if (current_keys[mode].enc.iv != NULL)
475     free(current_keys[mode].enc.iv);
476     if (current_keys[mode].enc.key != NULL)
477     free(current_keys[mode].enc.key);
478     if (current_keys[mode].mac.key != NULL)
479     free(current_keys[mode].mac.key);
480     #endif
481    
482     // setting
483     current_keys[mode].enc.iv = keys[ctos ? 0 : 1];
484     current_keys[mode].enc.key = keys[ctos ? 2 : 3];
485     current_keys[mode].mac.key = keys[ctos ? 4 : 5];
486    
487     //debug_print(20 + mode*3, current_keys[mode]->enc.iv, 8);
488     //debug_print(21 + mode*3, current_keys[mode]->enc.key, 24);
489     //debug_print(22 + mode*3, current_keys[mode]->mac.key, 24);
490     }
491     }

SourceForge.JP is a Japanese version of SourceForge.net. For developments that are not related to Japan, we recommend you to use SourceForge.net.