Mercurial > dropbear
comparison svr-kex.c @ 910:89555751c489 asm
merge up to 2013.63, improve ASM makefile rules a bit
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Thu, 27 Feb 2014 21:35:58 +0800 |
parents | cbc73a5aefb0 |
children | fd2e8bbb0333 |
comparison
equal
deleted
inserted
replaced
909:e4b75744acab | 910:89555751c489 |
---|---|
30 #include "session.h" | 30 #include "session.h" |
31 #include "kex.h" | 31 #include "kex.h" |
32 #include "ssh.h" | 32 #include "ssh.h" |
33 #include "packet.h" | 33 #include "packet.h" |
34 #include "bignum.h" | 34 #include "bignum.h" |
35 #include "random.h" | 35 #include "dbrandom.h" |
36 #include "runopts.h" | 36 #include "runopts.h" |
37 | 37 #include "ecc.h" |
38 | 38 #include "gensignkey.h" |
39 static void send_msg_kexdh_reply(mp_int *dh_e); | 39 |
40 static void send_msg_kexdh_reply(mp_int *dh_e, buffer *ecdh_qs); | |
40 | 41 |
41 /* Handle a diffie-hellman key exchange initialisation. This involves | 42 /* Handle a diffie-hellman key exchange initialisation. This involves |
42 * calculating a session key reply value, and corresponding hash. These | 43 * calculating a session key reply value, and corresponding hash. These |
43 * are carried out by send_msg_kexdh_reply(). recv_msg_kexdh_init() calls | 44 * are carried out by send_msg_kexdh_reply(). recv_msg_kexdh_init() calls |
44 * that function, then brings the new keys into use */ | 45 * that function, then brings the new keys into use */ |
45 void recv_msg_kexdh_init() { | 46 void recv_msg_kexdh_init() { |
46 | 47 |
47 DEF_MP_INT(dh_e); | 48 DEF_MP_INT(dh_e); |
49 buffer *ecdh_qs = NULL; | |
48 | 50 |
49 TRACE(("enter recv_msg_kexdh_init")) | 51 TRACE(("enter recv_msg_kexdh_init")) |
50 if (!ses.kexstate.recvkexinit) { | 52 if (!ses.kexstate.recvkexinit) { |
51 dropbear_exit("Premature kexdh_init message received"); | 53 dropbear_exit("Premature kexdh_init message received"); |
52 } | 54 } |
53 | 55 |
54 m_mp_init(&dh_e); | 56 switch (ses.newkeys->algo_kex->mode) { |
55 if (buf_getmpint(ses.payload, &dh_e) != DROPBEAR_SUCCESS) { | 57 case DROPBEAR_KEX_NORMAL_DH: |
56 dropbear_exit("Failed to get kex value"); | 58 m_mp_init(&dh_e); |
57 } | 59 if (buf_getmpint(ses.payload, &dh_e) != DROPBEAR_SUCCESS) { |
58 | 60 dropbear_exit("Bad kex value"); |
59 send_msg_kexdh_reply(&dh_e); | 61 } |
62 break; | |
63 case DROPBEAR_KEX_ECDH: | |
64 case DROPBEAR_KEX_CURVE25519: | |
65 #if defined(DROPBEAR_ECDH) || defined(DROPBEAR_CURVE25519) | |
66 ecdh_qs = buf_getstringbuf(ses.payload); | |
67 #endif | |
68 break; | |
69 } | |
70 if (ses.payload->pos != ses.payload->len) { | |
71 dropbear_exit("Bad kex value"); | |
72 } | |
73 | |
74 send_msg_kexdh_reply(&dh_e, ecdh_qs); | |
60 | 75 |
61 mp_clear(&dh_e); | 76 mp_clear(&dh_e); |
77 if (ecdh_qs) { | |
78 buf_free(ecdh_qs); | |
79 ecdh_qs = NULL; | |
80 } | |
62 | 81 |
63 send_msg_newkeys(); | 82 send_msg_newkeys(); |
64 ses.requirenext[0] = SSH_MSG_NEWKEYS; | 83 ses.requirenext = SSH_MSG_NEWKEYS; |
65 ses.requirenext[1] = 0; | |
66 TRACE(("leave recv_msg_kexdh_init")) | 84 TRACE(("leave recv_msg_kexdh_init")) |
67 } | 85 } |
86 | |
87 #ifdef DROPBEAR_DELAY_HOSTKEY | |
88 static void svr_ensure_hostkey() { | |
89 | |
90 const char* fn = NULL; | |
91 char *fn_temp = NULL; | |
92 enum signkey_type type = ses.newkeys->algo_hostkey; | |
93 void **hostkey = signkey_key_ptr(svr_opts.hostkey, type); | |
94 int ret = DROPBEAR_FAILURE; | |
95 | |
96 if (hostkey && *hostkey) { | |
97 return; | |
98 } | |
99 | |
100 switch (type) | |
101 { | |
102 #ifdef DROPBEAR_RSA | |
103 case DROPBEAR_SIGNKEY_RSA: | |
104 fn = RSA_PRIV_FILENAME; | |
105 break; | |
106 #endif | |
107 #ifdef DROPBEAR_DSS | |
108 case DROPBEAR_SIGNKEY_DSS: | |
109 fn = DSS_PRIV_FILENAME; | |
110 break; | |
111 #endif | |
112 #ifdef DROPBEAR_ECDSA | |
113 case DROPBEAR_SIGNKEY_ECDSA_NISTP256: | |
114 case DROPBEAR_SIGNKEY_ECDSA_NISTP384: | |
115 case DROPBEAR_SIGNKEY_ECDSA_NISTP521: | |
116 fn = ECDSA_PRIV_FILENAME; | |
117 break; | |
118 #endif | |
119 default: | |
120 (void)0; | |
121 } | |
122 | |
123 if (readhostkey(fn, svr_opts.hostkey, &type) == DROPBEAR_SUCCESS) { | |
124 return; | |
125 } | |
126 | |
127 fn_temp = m_malloc(strlen(fn) + 20); | |
128 snprintf(fn_temp, strlen(fn)+20, "%s.tmp%d", fn, getpid()); | |
129 | |
130 if (signkey_generate(type, 0, fn_temp) == DROPBEAR_FAILURE) { | |
131 goto out; | |
132 } | |
133 | |
134 if (link(fn_temp, fn) < 0) { | |
135 /* It's OK to get EEXIST - we probably just lost a race | |
136 with another connection to generate the key */ | |
137 if (errno != EEXIST) { | |
138 dropbear_log(LOG_ERR, "Failed moving key file to %s: %s", fn, | |
139 strerror(errno)); | |
140 /* XXX fallback to non-atomic copy for some filesystems? */ | |
141 goto out; | |
142 } | |
143 } | |
144 | |
145 ret = readhostkey(fn, svr_opts.hostkey, &type); | |
146 | |
147 if (ret == DROPBEAR_SUCCESS) { | |
148 char *fp = NULL; | |
149 unsigned int len; | |
150 buffer *key_buf = buf_new(MAX_PUBKEY_SIZE); | |
151 buf_put_pub_key(key_buf, svr_opts.hostkey, type); | |
152 buf_setpos(key_buf, 4); | |
153 len = key_buf->len - key_buf->pos; | |
154 fp = sign_key_fingerprint(buf_getptr(key_buf, len), len); | |
155 dropbear_log(LOG_INFO, "Generated hostkey %s, fingerprint is %s", | |
156 fn, fp); | |
157 m_free(fp); | |
158 buf_free(key_buf); | |
159 } | |
160 | |
161 out: | |
162 if (fn_temp) { | |
163 unlink(fn_temp); | |
164 m_free(fn_temp); | |
165 } | |
166 | |
167 if (ret == DROPBEAR_FAILURE) | |
168 { | |
169 dropbear_exit("Couldn't read or generate hostkey %s", fn); | |
170 } | |
171 } | |
172 #endif | |
68 | 173 |
69 /* Generate our side of the diffie-hellman key exchange value (dh_f), and | 174 /* Generate our side of the diffie-hellman key exchange value (dh_f), and |
70 * calculate the session key using the diffie-hellman algorithm. Following | 175 * calculate the session key using the diffie-hellman algorithm. Following |
71 * that, the session hash is calculated, and signed with RSA or DSS. The | 176 * that, the session hash is calculated, and signed with RSA or DSS. The |
72 * result is sent to the client. | 177 * result is sent to the client. |
73 * | 178 * |
74 * See the transport rfc 4253 section 8 for details */ | 179 * See the transport RFC4253 section 8 for details |
75 static void send_msg_kexdh_reply(mp_int *dh_e) { | 180 * or RFC5656 section 4 for elliptic curve variant. */ |
76 | 181 static void send_msg_kexdh_reply(mp_int *dh_e, buffer *ecdh_qs) { |
77 DEF_MP_INT(dh_y); | |
78 DEF_MP_INT(dh_f); | |
79 | |
80 TRACE(("enter send_msg_kexdh_reply")) | 182 TRACE(("enter send_msg_kexdh_reply")) |
81 m_mp_init_multi(&dh_y, &dh_f, NULL); | |
82 | |
83 gen_kexdh_vals(&dh_f, &dh_y); | |
84 | |
85 kexdh_comb_key(&dh_f, &dh_y, dh_e, svr_opts.hostkey); | |
86 mp_clear(&dh_y); | |
87 | 183 |
88 /* we can start creating the kexdh_reply packet */ | 184 /* we can start creating the kexdh_reply packet */ |
89 CHECKCLEARTOWRITE(); | 185 CHECKCLEARTOWRITE(); |
186 | |
187 #ifdef DROPBEAR_DELAY_HOSTKEY | |
188 if (svr_opts.delay_hostkey) | |
189 { | |
190 svr_ensure_hostkey(); | |
191 } | |
192 #endif | |
193 | |
90 buf_putbyte(ses.writepayload, SSH_MSG_KEXDH_REPLY); | 194 buf_putbyte(ses.writepayload, SSH_MSG_KEXDH_REPLY); |
91 buf_put_pub_key(ses.writepayload, svr_opts.hostkey, | 195 buf_put_pub_key(ses.writepayload, svr_opts.hostkey, |
92 ses.newkeys->algo_hostkey); | 196 ses.newkeys->algo_hostkey); |
93 | 197 |
94 /* put f */ | 198 switch (ses.newkeys->algo_kex->mode) { |
95 buf_putmpint(ses.writepayload, &dh_f); | 199 case DROPBEAR_KEX_NORMAL_DH: |
96 mp_clear(&dh_f); | 200 { |
201 struct kex_dh_param * dh_param = gen_kexdh_param(); | |
202 kexdh_comb_key(dh_param, dh_e, svr_opts.hostkey); | |
203 | |
204 /* put f */ | |
205 buf_putmpint(ses.writepayload, &dh_param->pub); | |
206 free_kexdh_param(dh_param); | |
207 } | |
208 break; | |
209 case DROPBEAR_KEX_ECDH: | |
210 #ifdef DROPBEAR_ECDH | |
211 { | |
212 struct kex_ecdh_param *ecdh_param = gen_kexecdh_param(); | |
213 kexecdh_comb_key(ecdh_param, ecdh_qs, svr_opts.hostkey); | |
214 | |
215 buf_put_ecc_raw_pubkey_string(ses.writepayload, &ecdh_param->key); | |
216 free_kexecdh_param(ecdh_param); | |
217 } | |
218 #endif | |
219 break; | |
220 case DROPBEAR_KEX_CURVE25519: | |
221 #ifdef DROPBEAR_CURVE25519 | |
222 { | |
223 struct kex_curve25519_param *param = gen_kexcurve25519_param(); | |
224 kexcurve25519_comb_key(param, ecdh_qs, svr_opts.hostkey); | |
225 buf_putstring(ses.writepayload, param->pub, CURVE25519_LEN); | |
226 free_kexcurve25519_param(param); | |
227 } | |
228 #endif | |
229 break; | |
230 } | |
97 | 231 |
98 /* calc the signature */ | 232 /* calc the signature */ |
99 buf_put_sign(ses.writepayload, svr_opts.hostkey, | 233 buf_put_sign(ses.writepayload, svr_opts.hostkey, |
100 ses.newkeys->algo_hostkey, ses.hash, SHA1_HASH_SIZE); | 234 ses.newkeys->algo_hostkey, ses.hash); |
101 | 235 |
102 /* the SSH_MSG_KEXDH_REPLY is done */ | 236 /* the SSH_MSG_KEXDH_REPLY is done */ |
103 encrypt_packet(); | 237 encrypt_packet(); |
104 | 238 |
105 TRACE(("leave send_msg_kexdh_reply")) | 239 TRACE(("leave send_msg_kexdh_reply")) |