comparison svr-kex.c @ 854:ccc76acaf4c7

merge ecc again
author Matt Johnston <matt@ucc.asn.au>
date Thu, 14 Nov 2013 20:45:46 +0800
parents 7540c0822374
children 220f55d540ae
comparison
equal deleted inserted replaced
845:774ad9b112ef 854:ccc76acaf4c7
33 #include "packet.h" 33 #include "packet.h"
34 #include "bignum.h" 34 #include "bignum.h"
35 #include "random.h" 35 #include "random.h"
36 #include "runopts.h" 36 #include "runopts.h"
37 #include "ecc.h" 37 #include "ecc.h"
38 #include "gensignkey.h"
38 39
39 static void send_msg_kexdh_reply(mp_int *dh_e, buffer *ecdh_qs); 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
50 TRACE(("enter recv_msg_kexdh_init")) 51 TRACE(("enter recv_msg_kexdh_init"))
51 if (!ses.kexstate.recvkexinit) { 52 if (!ses.kexstate.recvkexinit) {
52 dropbear_exit("Premature kexdh_init message received"); 53 dropbear_exit("Premature kexdh_init message received");
53 } 54 }
54 55
55 if (IS_NORMAL_DH(ses.newkeys->algo_kex)) { 56 switch (ses.newkeys->algo_kex->mode) {
56 m_mp_init(&dh_e); 57 case DROPBEAR_KEX_NORMAL_DH:
57 if (buf_getmpint(ses.payload, &dh_e) != DROPBEAR_SUCCESS) { 58 m_mp_init(&dh_e);
58 dropbear_exit("Failed to get kex value"); 59 if (buf_getmpint(ses.payload, &dh_e) != DROPBEAR_SUCCESS) {
59 } 60 dropbear_exit("Bad kex value");
60 } else { 61 }
61 #ifdef DROPBEAR_ECDH 62 break;
62 ecdh_qs = buf_getstringbuf(ses.payload); 63 case DROPBEAR_KEX_ECDH:
63 #endif 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");
64 } 72 }
65 73
66 send_msg_kexdh_reply(&dh_e, ecdh_qs); 74 send_msg_kexdh_reply(&dh_e, ecdh_qs);
67 75
68 mp_clear(&dh_e); 76 mp_clear(&dh_e);
69 if (ecdh_qs) { 77 if (ecdh_qs) {
70 buf_free(ecdh_qs); 78 buf_free(ecdh_qs);
79 ecdh_qs = NULL;
71 } 80 }
72 81
73 send_msg_newkeys(); 82 send_msg_newkeys();
74 ses.requirenext[0] = SSH_MSG_NEWKEYS; 83 ses.requirenext[0] = SSH_MSG_NEWKEYS;
75 ses.requirenext[1] = 0; 84 ses.requirenext[1] = 0;
76 TRACE(("leave recv_msg_kexdh_init")) 85 TRACE(("leave recv_msg_kexdh_init"))
77 } 86 }
87
88 #ifdef DROPBEAR_DELAY_HOSTKEY
89 static void svr_ensure_hostkey() {
90
91 const char* fn = NULL;
92 char *fn_temp = NULL;
93 enum signkey_type type = ses.newkeys->algo_hostkey;
94 void **hostkey = signkey_key_ptr(svr_opts.hostkey, type);
95 int ret = DROPBEAR_FAILURE;
96
97 if (hostkey && *hostkey) {
98 return;
99 }
100
101 switch (type)
102 {
103 #ifdef DROPBEAR_RSA
104 case DROPBEAR_SIGNKEY_RSA:
105 fn = RSA_PRIV_FILENAME;
106 break;
107 #endif
108 #ifdef DROPBEAR_DSS
109 case DROPBEAR_SIGNKEY_DSS:
110 fn = DSS_PRIV_FILENAME;
111 break;
112 #endif
113 #ifdef DROPBEAR_ECDSA
114 case DROPBEAR_SIGNKEY_ECDSA_NISTP256:
115 case DROPBEAR_SIGNKEY_ECDSA_NISTP384:
116 case DROPBEAR_SIGNKEY_ECDSA_NISTP521:
117 fn = ECDSA_PRIV_FILENAME;
118 break;
119 #endif
120 default:
121 (void)0;
122 }
123
124 if (readhostkey(fn, svr_opts.hostkey, &type) == DROPBEAR_SUCCESS) {
125 return;
126 }
127
128 fn_temp = m_malloc(strlen(fn) + 20);
129 snprintf(fn_temp, strlen(fn)+20, "%s.tmp%d", fn, getpid());
130
131 if (signkey_generate(type, 0, fn_temp) == DROPBEAR_FAILURE) {
132 goto out;
133 }
134
135 if (link(fn_temp, fn) < 0) {
136 /* It's OK to get EEXIST - we probably just lost a race
137 with another connection to generate the key */
138 if (errno != EEXIST) {
139 dropbear_log(LOG_ERR, "Failed moving key file to %s: %s", fn,
140 strerror(errno));
141 /* XXX fallback to non-atomic copy for some filesystems? */
142 goto out;
143 }
144 }
145
146 ret = readhostkey(fn, svr_opts.hostkey, &type);
147
148 out:
149 if (fn_temp) {
150 unlink(fn_temp);
151 m_free(fn_temp);
152 }
153
154 if (ret == DROPBEAR_FAILURE)
155 {
156 dropbear_exit("Couldn't read or generate hostkey %s", fn);
157 }
158 }
159 #endif
78 160
79 /* Generate our side of the diffie-hellman key exchange value (dh_f), and 161 /* Generate our side of the diffie-hellman key exchange value (dh_f), and
80 * calculate the session key using the diffie-hellman algorithm. Following 162 * calculate the session key using the diffie-hellman algorithm. Following
81 * that, the session hash is calculated, and signed with RSA or DSS. The 163 * that, the session hash is calculated, and signed with RSA or DSS. The
82 * result is sent to the client. 164 * result is sent to the client.
86 static void send_msg_kexdh_reply(mp_int *dh_e, buffer *ecdh_qs) { 168 static void send_msg_kexdh_reply(mp_int *dh_e, buffer *ecdh_qs) {
87 TRACE(("enter send_msg_kexdh_reply")) 169 TRACE(("enter send_msg_kexdh_reply"))
88 170
89 /* we can start creating the kexdh_reply packet */ 171 /* we can start creating the kexdh_reply packet */
90 CHECKCLEARTOWRITE(); 172 CHECKCLEARTOWRITE();
173
174 #ifdef DROPBEAR_DELAY_HOSTKEY
175 if (svr_opts.delay_hostkey)
176 {
177 svr_ensure_hostkey();
178 }
179 #endif
180
91 buf_putbyte(ses.writepayload, SSH_MSG_KEXDH_REPLY); 181 buf_putbyte(ses.writepayload, SSH_MSG_KEXDH_REPLY);
92 buf_put_pub_key(ses.writepayload, svr_opts.hostkey, 182 buf_put_pub_key(ses.writepayload, svr_opts.hostkey,
93 ses.newkeys->algo_hostkey); 183 ses.newkeys->algo_hostkey);
94 184
95 if (IS_NORMAL_DH(ses.newkeys->algo_kex)) { 185 switch (ses.newkeys->algo_kex->mode) {
96 // Normal diffie-hellman 186 case DROPBEAR_KEX_NORMAL_DH:
97 struct kex_dh_param * dh_param = gen_kexdh_param(); 187 {
98 kexdh_comb_key(dh_param, dh_e, svr_opts.hostkey); 188 struct kex_dh_param * dh_param = gen_kexdh_param();
99 189 kexdh_comb_key(dh_param, dh_e, svr_opts.hostkey);
100 /* put f */ 190
101 buf_putmpint(ses.writepayload, &dh_param->pub); 191 /* put f */
102 free_kexdh_param(dh_param); 192 buf_putmpint(ses.writepayload, &dh_param->pub);
103 } else { 193 free_kexdh_param(dh_param);
194 }
195 break;
196 case DROPBEAR_KEX_ECDH:
104 #ifdef DROPBEAR_ECDH 197 #ifdef DROPBEAR_ECDH
105 struct kex_ecdh_param *ecdh_param = gen_kexecdh_param(); 198 {
106 kexecdh_comb_key(ecdh_param, ecdh_qs, svr_opts.hostkey); 199 struct kex_ecdh_param *ecdh_param = gen_kexecdh_param();
107 200 kexecdh_comb_key(ecdh_param, ecdh_qs, svr_opts.hostkey);
108 buf_put_ecc_raw_pubkey_string(ses.writepayload, &ecdh_param->key); 201
109 free_kexecdh_param(ecdh_param); 202 buf_put_ecc_raw_pubkey_string(ses.writepayload, &ecdh_param->key);
110 #endif 203 free_kexecdh_param(ecdh_param);
204 }
205 #endif
206 break;
207 case DROPBEAR_KEX_CURVE25519:
208 #ifdef DROPBEAR_CURVE25519
209 {
210 struct kex_curve25519_param *param = gen_kexcurve25519_param();
211 kexcurve25519_comb_key(param, ecdh_qs, svr_opts.hostkey);
212 buf_putstring(ses.writepayload, param->pub, CURVE25519_LEN);
213 free_kexcurve25519_param(param);
214 }
215 #endif
216 break;
111 } 217 }
112 218
113 /* calc the signature */ 219 /* calc the signature */
114 buf_put_sign(ses.writepayload, svr_opts.hostkey, 220 buf_put_sign(ses.writepayload, svr_opts.hostkey,
115 ses.newkeys->algo_hostkey, ses.hash); 221 ses.newkeys->algo_hostkey, ses.hash);