kexc25519.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. /* $OpenBSD: kexc25519.c,v 1.17 2019/01/21 10:40:11 djm Exp $ */
  2. /*
  3. * Copyright (c) 2019 Markus Friedl. All rights reserved.
  4. * Copyright (c) 2010 Damien Miller. All rights reserved.
  5. * Copyright (c) 2013 Aris Adamantiadis. All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  17. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  18. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  19. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  20. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  21. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  22. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  23. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  25. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. */
  27. #include "includes.h"
  28. #include <sys/types.h>
  29. #include <stdio.h>
  30. #include <string.h>
  31. #include <signal.h>
  32. #include "sshkey.h"
  33. #include "kex.h"
  34. #include "sshbuf.h"
  35. #include "digest.h"
  36. #include "ssherr.h"
  37. #include "ssh2.h"
  38. extern int crypto_scalarmult_curve25519(u_char a[CURVE25519_SIZE],
  39. const u_char b[CURVE25519_SIZE], const u_char c[CURVE25519_SIZE])
  40. __attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE)))
  41. __attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE)))
  42. __attribute__((__bounded__(__minbytes__, 3, CURVE25519_SIZE)));
  43. void
  44. kexc25519_keygen(u_char key[CURVE25519_SIZE], u_char pub[CURVE25519_SIZE])
  45. {
  46. static const u_char basepoint[CURVE25519_SIZE] = {9};
  47. arc4random_buf(key, CURVE25519_SIZE);
  48. crypto_scalarmult_curve25519(pub, key, basepoint);
  49. }
  50. int
  51. kexc25519_shared_key_ext(const u_char key[CURVE25519_SIZE],
  52. const u_char pub[CURVE25519_SIZE], struct sshbuf *out, int raw)
  53. {
  54. u_char shared_key[CURVE25519_SIZE];
  55. u_char zero[CURVE25519_SIZE];
  56. int r;
  57. crypto_scalarmult_curve25519(shared_key, key, pub);
  58. /* Check for all-zero shared secret */
  59. explicit_bzero(zero, CURVE25519_SIZE);
  60. if (timingsafe_bcmp(zero, shared_key, CURVE25519_SIZE) == 0)
  61. return SSH_ERR_KEY_INVALID_EC_VALUE;
  62. #ifdef DEBUG_KEXECDH
  63. dump_digest("shared secret", shared_key, CURVE25519_SIZE);
  64. #endif
  65. if (raw)
  66. r = sshbuf_put(out, shared_key, CURVE25519_SIZE);
  67. else
  68. r = sshbuf_put_bignum2_bytes(out, shared_key, CURVE25519_SIZE);
  69. explicit_bzero(shared_key, CURVE25519_SIZE);
  70. return r;
  71. }
  72. int
  73. kexc25519_shared_key(const u_char key[CURVE25519_SIZE],
  74. const u_char pub[CURVE25519_SIZE], struct sshbuf *out)
  75. {
  76. return kexc25519_shared_key_ext(key, pub, out, 0);
  77. }
  78. int
  79. kex_c25519_keypair(struct kex *kex)
  80. {
  81. struct sshbuf *buf = NULL;
  82. u_char *cp = NULL;
  83. int r;
  84. if ((buf = sshbuf_new()) == NULL)
  85. return SSH_ERR_ALLOC_FAIL;
  86. if ((r = sshbuf_reserve(buf, CURVE25519_SIZE, &cp)) != 0)
  87. goto out;
  88. kexc25519_keygen(kex->c25519_client_key, cp);
  89. #ifdef DEBUG_KEXECDH
  90. dump_digest("client public key c25519:", cp, CURVE25519_SIZE);
  91. #endif
  92. kex->client_pub = buf;
  93. buf = NULL;
  94. out:
  95. sshbuf_free(buf);
  96. return r;
  97. }
  98. int
  99. kex_c25519_enc(struct kex *kex, const struct sshbuf *client_blob,
  100. struct sshbuf **server_blobp, struct sshbuf **shared_secretp)
  101. {
  102. struct sshbuf *server_blob = NULL;
  103. struct sshbuf *buf = NULL;
  104. const u_char *client_pub;
  105. u_char *server_pub;
  106. u_char server_key[CURVE25519_SIZE];
  107. int r;
  108. *server_blobp = NULL;
  109. *shared_secretp = NULL;
  110. if (sshbuf_len(client_blob) != CURVE25519_SIZE) {
  111. r = SSH_ERR_SIGNATURE_INVALID;
  112. goto out;
  113. }
  114. client_pub = sshbuf_ptr(client_blob);
  115. #ifdef DEBUG_KEXECDH
  116. dump_digest("client public key 25519:", client_pub, CURVE25519_SIZE);
  117. #endif
  118. /* allocate space for encrypted KEM key and ECDH pub key */
  119. if ((server_blob = sshbuf_new()) == NULL) {
  120. r = SSH_ERR_ALLOC_FAIL;
  121. goto out;
  122. }
  123. if ((r = sshbuf_reserve(server_blob, CURVE25519_SIZE, &server_pub)) != 0)
  124. goto out;
  125. kexc25519_keygen(server_key, server_pub);
  126. /* allocate shared secret */
  127. if ((buf = sshbuf_new()) == NULL) {
  128. r = SSH_ERR_ALLOC_FAIL;
  129. goto out;
  130. }
  131. if ((r = kexc25519_shared_key_ext(server_key, client_pub, buf, 0)) < 0)
  132. goto out;
  133. #ifdef DEBUG_KEXECDH
  134. dump_digest("server public key 25519:", server_pub, CURVE25519_SIZE);
  135. dump_digest("encoded shared secret:", sshbuf_ptr(buf), sshbuf_len(buf));
  136. #endif
  137. *server_blobp = server_blob;
  138. *shared_secretp = buf;
  139. server_blob = NULL;
  140. buf = NULL;
  141. out:
  142. explicit_bzero(server_key, sizeof(server_key));
  143. sshbuf_free(server_blob);
  144. sshbuf_free(buf);
  145. return r;
  146. }
  147. int
  148. kex_c25519_dec(struct kex *kex, const struct sshbuf *server_blob,
  149. struct sshbuf **shared_secretp)
  150. {
  151. struct sshbuf *buf = NULL;
  152. const u_char *server_pub;
  153. int r;
  154. *shared_secretp = NULL;
  155. if (sshbuf_len(server_blob) != CURVE25519_SIZE) {
  156. r = SSH_ERR_SIGNATURE_INVALID;
  157. goto out;
  158. }
  159. server_pub = sshbuf_ptr(server_blob);
  160. #ifdef DEBUG_KEXECDH
  161. dump_digest("server public key c25519:", server_pub, CURVE25519_SIZE);
  162. #endif
  163. /* shared secret */
  164. if ((buf = sshbuf_new()) == NULL) {
  165. r = SSH_ERR_ALLOC_FAIL;
  166. goto out;
  167. }
  168. if ((r = kexc25519_shared_key_ext(kex->c25519_client_key, server_pub,
  169. buf, 0)) < 0)
  170. goto out;
  171. #ifdef DEBUG_KEXECDH
  172. dump_digest("encoded shared secret:", sshbuf_ptr(buf), sshbuf_len(buf));
  173. #endif
  174. *shared_secretp = buf;
  175. buf = NULL;
  176. out:
  177. sshbuf_free(buf);
  178. return r;
  179. }