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"))