Mercurial > dropbear
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); |