kexgexs.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. /* $OpenBSD: kexgexs.c,v 1.42 2019/01/23 00:30:41 djm Exp $ */
  2. /*
  3. * Copyright (c) 2000 Niels Provos. All rights reserved.
  4. * Copyright (c) 2001 Markus Friedl. All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. *
  15. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  16. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  17. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  18. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  19. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  20. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  21. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  22. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  23. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  24. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25. */
  26. #include "includes.h"
  27. #ifdef WITH_OPENSSL
  28. #include <stdarg.h>
  29. #include <stdio.h>
  30. #include <string.h>
  31. #include <signal.h>
  32. #include <openssl/dh.h>
  33. #include "openbsd-compat/openssl-compat.h"
  34. #include "sshkey.h"
  35. #include "cipher.h"
  36. #include "digest.h"
  37. #include "kex.h"
  38. #include "log.h"
  39. #include "packet.h"
  40. #include "dh.h"
  41. #include "ssh2.h"
  42. #include "compat.h"
  43. #ifdef GSSAPI
  44. #include "ssh-gss.h"
  45. #endif
  46. #include "monitor_wrap.h"
  47. #include "dispatch.h"
  48. #include "ssherr.h"
  49. #include "sshbuf.h"
  50. #include "misc.h"
  51. static int input_kex_dh_gex_request(int, u_int32_t, struct ssh *);
  52. static int input_kex_dh_gex_init(int, u_int32_t, struct ssh *);
  53. int
  54. kexgex_server(struct ssh *ssh)
  55. {
  56. ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_REQUEST,
  57. &input_kex_dh_gex_request);
  58. debug("expecting SSH2_MSG_KEX_DH_GEX_REQUEST");
  59. return 0;
  60. }
  61. static int
  62. input_kex_dh_gex_request(int type, u_int32_t seq, struct ssh *ssh)
  63. {
  64. struct kex *kex = ssh->kex;
  65. int r;
  66. u_int min = 0, max = 0, nbits = 0;
  67. const BIGNUM *dh_p, *dh_g;
  68. debug("SSH2_MSG_KEX_DH_GEX_REQUEST received");
  69. ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_REQUEST, &kex_protocol_error);
  70. if ((r = sshpkt_get_u32(ssh, &min)) != 0 ||
  71. (r = sshpkt_get_u32(ssh, &nbits)) != 0 ||
  72. (r = sshpkt_get_u32(ssh, &max)) != 0 ||
  73. (r = sshpkt_get_end(ssh)) != 0)
  74. goto out;
  75. kex->nbits = nbits;
  76. kex->min = min;
  77. kex->max = max;
  78. min = MAXIMUM(DH_GRP_MIN, min);
  79. max = MINIMUM(DH_GRP_MAX, max);
  80. nbits = MAXIMUM(DH_GRP_MIN, nbits);
  81. nbits = MINIMUM(DH_GRP_MAX, nbits);
  82. if (kex->max < kex->min || kex->nbits < kex->min ||
  83. kex->max < kex->nbits || kex->max < DH_GRP_MIN) {
  84. r = SSH_ERR_DH_GEX_OUT_OF_RANGE;
  85. goto out;
  86. }
  87. /* Contact privileged parent */
  88. kex->dh = PRIVSEP(choose_dh(min, nbits, max));
  89. if (kex->dh == NULL) {
  90. sshpkt_disconnect(ssh, "no matching DH grp found");
  91. r = SSH_ERR_ALLOC_FAIL;
  92. goto out;
  93. }
  94. debug("SSH2_MSG_KEX_DH_GEX_GROUP sent");
  95. DH_get0_pqg(kex->dh, &dh_p, NULL, &dh_g);
  96. if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_DH_GEX_GROUP)) != 0 ||
  97. (r = sshpkt_put_bignum2(ssh, dh_p)) != 0 ||
  98. (r = sshpkt_put_bignum2(ssh, dh_g)) != 0 ||
  99. (r = sshpkt_send(ssh)) != 0)
  100. goto out;
  101. /* Compute our exchange value in parallel with the client */
  102. if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0)
  103. goto out;
  104. debug("expecting SSH2_MSG_KEX_DH_GEX_INIT");
  105. ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_INIT, &input_kex_dh_gex_init);
  106. r = 0;
  107. out:
  108. return r;
  109. }
  110. static int
  111. input_kex_dh_gex_init(int type, u_int32_t seq, struct ssh *ssh)
  112. {
  113. struct kex *kex = ssh->kex;
  114. BIGNUM *dh_client_pub = NULL;
  115. const BIGNUM *pub_key, *dh_p, *dh_g;
  116. struct sshbuf *shared_secret = NULL;
  117. struct sshbuf *server_host_key_blob = NULL;
  118. struct sshkey *server_host_public, *server_host_private;
  119. u_char *signature = NULL;
  120. u_char hash[SSH_DIGEST_MAX_LENGTH];
  121. size_t slen, hashlen;
  122. int r;
  123. debug("SSH2_MSG_KEX_DH_GEX_INIT received");
  124. ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_INIT, &kex_protocol_error);
  125. if ((r = kex_load_hostkey(ssh, &server_host_private,
  126. &server_host_public)) != 0)
  127. goto out;
  128. /* key, cert */
  129. if ((r = sshpkt_get_bignum2(ssh, &dh_client_pub)) != 0 ||
  130. (r = sshpkt_get_end(ssh)) != 0)
  131. goto out;
  132. if ((shared_secret = sshbuf_new()) == NULL) {
  133. r = SSH_ERR_ALLOC_FAIL;
  134. goto out;
  135. }
  136. if ((r = kex_dh_compute_key(kex, dh_client_pub, shared_secret)) != 0)
  137. goto out;
  138. if ((server_host_key_blob = sshbuf_new()) == NULL) {
  139. r = SSH_ERR_ALLOC_FAIL;
  140. goto out;
  141. }
  142. if ((r = sshkey_putb(server_host_public, server_host_key_blob)) != 0)
  143. goto out;
  144. /* calc H */
  145. DH_get0_key(kex->dh, &pub_key, NULL);
  146. DH_get0_pqg(kex->dh, &dh_p, NULL, &dh_g);
  147. hashlen = sizeof(hash);
  148. if ((r = kexgex_hash(
  149. kex->hash_alg,
  150. kex->client_version,
  151. kex->server_version,
  152. kex->peer,
  153. kex->my,
  154. server_host_key_blob,
  155. kex->min, kex->nbits, kex->max,
  156. dh_p, dh_g,
  157. dh_client_pub,
  158. pub_key,
  159. sshbuf_ptr(shared_secret), sshbuf_len(shared_secret),
  160. hash, &hashlen)) != 0)
  161. goto out;
  162. /* sign H */
  163. if ((r = kex->sign(ssh, server_host_private, server_host_public,
  164. &signature, &slen, hash, hashlen, kex->hostkey_alg)) < 0)
  165. goto out;
  166. /* send server hostkey, DH pubkey 'f' and signed H */
  167. if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_DH_GEX_REPLY)) != 0 ||
  168. (r = sshpkt_put_stringb(ssh, server_host_key_blob)) != 0 ||
  169. (r = sshpkt_put_bignum2(ssh, pub_key)) != 0 || /* f */
  170. (r = sshpkt_put_string(ssh, signature, slen)) != 0 ||
  171. (r = sshpkt_send(ssh)) != 0)
  172. goto out;
  173. if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0)
  174. r = kex_send_newkeys(ssh);
  175. out:
  176. explicit_bzero(hash, sizeof(hash));
  177. DH_free(kex->dh);
  178. kex->dh = NULL;
  179. BN_clear_free(dh_client_pub);
  180. sshbuf_free(shared_secret);
  181. sshbuf_free(server_host_key_blob);
  182. free(signature);
  183. return r;
  184. }
  185. #endif /* WITH_OPENSSL */