svr-kex.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. /*
  2. * Dropbear - a SSH2 server
  3. *
  4. * Copyright (c) 2002,2003 Matt Johnston
  5. * Copyright (c) 2004 by Mihnea Stoenescu
  6. * All rights reserved.
  7. *
  8. * Permission is hereby granted, free of charge, to any person obtaining a copy
  9. * of this software and associated documentation files (the "Software"), to deal
  10. * in the Software without restriction, including without limitation the rights
  11. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  12. * copies of the Software, and to permit persons to whom the Software is
  13. * furnished to do so, subject to the following conditions:
  14. *
  15. * The above copyright notice and this permission notice shall be included in
  16. * all copies or substantial portions of the Software.
  17. *
  18. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  19. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  20. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  21. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  22. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  23. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  24. * SOFTWARE. */
  25. #include "includes.h"
  26. #include "dbutil.h"
  27. #include "algo.h"
  28. #include "buffer.h"
  29. #include "session.h"
  30. #include "kex.h"
  31. #include "ssh.h"
  32. #include "packet.h"
  33. #include "bignum.h"
  34. #include "dbrandom.h"
  35. #include "runopts.h"
  36. #include "ecc.h"
  37. #include "gensignkey.h"
  38. static void send_msg_kexdh_reply(mp_int *dh_e, buffer *ecdh_qs);
  39. /* Handle a diffie-hellman key exchange initialisation. This involves
  40. * calculating a session key reply value, and corresponding hash. These
  41. * are carried out by send_msg_kexdh_reply(). recv_msg_kexdh_init() calls
  42. * that function, then brings the new keys into use */
  43. void recv_msg_kexdh_init() {
  44. DEF_MP_INT(dh_e);
  45. buffer *ecdh_qs = NULL;
  46. TRACE(("enter recv_msg_kexdh_init"))
  47. if (!ses.kexstate.recvkexinit) {
  48. dropbear_exit("Premature kexdh_init message received");
  49. }
  50. switch (ses.newkeys->algo_kex->mode) {
  51. case DROPBEAR_KEX_NORMAL_DH:
  52. m_mp_init(&dh_e);
  53. if (buf_getmpint(ses.payload, &dh_e) != DROPBEAR_SUCCESS) {
  54. dropbear_exit("Bad kex value");
  55. }
  56. break;
  57. case DROPBEAR_KEX_ECDH:
  58. case DROPBEAR_KEX_CURVE25519:
  59. #if defined(DROPBEAR_ECDH) || defined(DROPBEAR_CURVE25519)
  60. ecdh_qs = buf_getstringbuf(ses.payload);
  61. #endif
  62. break;
  63. }
  64. if (ses.payload->pos != ses.payload->len) {
  65. dropbear_exit("Bad kex value");
  66. }
  67. send_msg_kexdh_reply(&dh_e, ecdh_qs);
  68. mp_clear(&dh_e);
  69. if (ecdh_qs) {
  70. buf_free(ecdh_qs);
  71. ecdh_qs = NULL;
  72. }
  73. send_msg_newkeys();
  74. ses.requirenext = SSH_MSG_NEWKEYS;
  75. TRACE(("leave recv_msg_kexdh_init"))
  76. }
  77. #ifdef DROPBEAR_DELAY_HOSTKEY
  78. static void svr_ensure_hostkey() {
  79. const char* fn = NULL;
  80. enum signkey_type type = ses.newkeys->algo_hostkey;
  81. void **hostkey = signkey_key_ptr(svr_opts.hostkey, type);
  82. int ret = DROPBEAR_FAILURE;
  83. if (hostkey && *hostkey) {
  84. return;
  85. }
  86. switch (type)
  87. {
  88. #ifdef DROPBEAR_RSA
  89. case DROPBEAR_SIGNKEY_RSA:
  90. fn = RSA_PRIV_FILENAME;
  91. break;
  92. #endif
  93. #ifdef DROPBEAR_DSS
  94. case DROPBEAR_SIGNKEY_DSS:
  95. fn = DSS_PRIV_FILENAME;
  96. break;
  97. #endif
  98. #ifdef DROPBEAR_ECDSA
  99. case DROPBEAR_SIGNKEY_ECDSA_NISTP256:
  100. case DROPBEAR_SIGNKEY_ECDSA_NISTP384:
  101. case DROPBEAR_SIGNKEY_ECDSA_NISTP521:
  102. fn = ECDSA_PRIV_FILENAME;
  103. break;
  104. #endif
  105. default:
  106. dropbear_assert(0);
  107. }
  108. if (readhostkey(fn, svr_opts.hostkey, &type) == DROPBEAR_SUCCESS) {
  109. return;
  110. }
  111. if (signkey_generate(type, 0, fn, 1) == DROPBEAR_FAILURE) {
  112. goto out;
  113. }
  114. ret = readhostkey(fn, svr_opts.hostkey, &type);
  115. if (ret == DROPBEAR_SUCCESS) {
  116. char *fp = NULL;
  117. unsigned int len;
  118. buffer *key_buf = buf_new(MAX_PUBKEY_SIZE);
  119. buf_put_pub_key(key_buf, svr_opts.hostkey, type);
  120. buf_setpos(key_buf, 4);
  121. len = key_buf->len - key_buf->pos;
  122. fp = sign_key_fingerprint(buf_getptr(key_buf, len), len);
  123. dropbear_log(LOG_INFO, "Generated hostkey %s, fingerprint is %s",
  124. fn, fp);
  125. m_free(fp);
  126. buf_free(key_buf);
  127. }
  128. out:
  129. if (ret == DROPBEAR_FAILURE)
  130. {
  131. dropbear_exit("Couldn't read or generate hostkey %s", fn);
  132. }
  133. }
  134. #endif
  135. /* Generate our side of the diffie-hellman key exchange value (dh_f), and
  136. * calculate the session key using the diffie-hellman algorithm. Following
  137. * that, the session hash is calculated, and signed with RSA or DSS. The
  138. * result is sent to the client.
  139. *
  140. * See the transport RFC4253 section 8 for details
  141. * or RFC5656 section 4 for elliptic curve variant. */
  142. static void send_msg_kexdh_reply(mp_int *dh_e, buffer *ecdh_qs) {
  143. TRACE(("enter send_msg_kexdh_reply"))
  144. /* we can start creating the kexdh_reply packet */
  145. CHECKCLEARTOWRITE();
  146. #ifdef DROPBEAR_DELAY_HOSTKEY
  147. if (svr_opts.delay_hostkey)
  148. {
  149. svr_ensure_hostkey();
  150. }
  151. #endif
  152. buf_putbyte(ses.writepayload, SSH_MSG_KEXDH_REPLY);
  153. buf_put_pub_key(ses.writepayload, svr_opts.hostkey,
  154. ses.newkeys->algo_hostkey);
  155. switch (ses.newkeys->algo_kex->mode) {
  156. case DROPBEAR_KEX_NORMAL_DH:
  157. {
  158. struct kex_dh_param * dh_param = gen_kexdh_param();
  159. kexdh_comb_key(dh_param, dh_e, svr_opts.hostkey);
  160. /* put f */
  161. buf_putmpint(ses.writepayload, &dh_param->pub);
  162. free_kexdh_param(dh_param);
  163. }
  164. break;
  165. case DROPBEAR_KEX_ECDH:
  166. #ifdef DROPBEAR_ECDH
  167. {
  168. struct kex_ecdh_param *ecdh_param = gen_kexecdh_param();
  169. kexecdh_comb_key(ecdh_param, ecdh_qs, svr_opts.hostkey);
  170. buf_put_ecc_raw_pubkey_string(ses.writepayload, &ecdh_param->key);
  171. free_kexecdh_param(ecdh_param);
  172. }
  173. #endif
  174. break;
  175. case DROPBEAR_KEX_CURVE25519:
  176. #ifdef DROPBEAR_CURVE25519
  177. {
  178. struct kex_curve25519_param *param = gen_kexcurve25519_param();
  179. kexcurve25519_comb_key(param, ecdh_qs, svr_opts.hostkey);
  180. buf_putstring(ses.writepayload, (const char*)param->pub, CURVE25519_LEN);
  181. free_kexcurve25519_param(param);
  182. }
  183. #endif
  184. break;
  185. }
  186. /* calc the signature */
  187. buf_put_sign(ses.writepayload, svr_opts.hostkey,
  188. ses.newkeys->algo_hostkey, ses.hash);
  189. /* the SSH_MSG_KEXDH_REPLY is done */
  190. encrypt_packet();
  191. TRACE(("leave send_msg_kexdh_reply"))
  192. }