keygen_network.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. #include <stdint.h>
  2. #include <string.h>
  3. #include "crypto.h"
  4. #include "crypto_dh.h"
  5. #include "crypto_verify_bytes.h"
  6. #include "keygen.h"
  7. #include "netpacket.h"
  8. #include "netproto.h"
  9. #include "sysendian.h"
  10. #include "tsnetwork.h"
  11. #include "warnp.h"
  12. static sendpacket_callback callback_register_send;
  13. static handlepacket_callback callback_register_challenge;
  14. static handlepacket_callback callback_register_response;
  15. /**
  16. * keygen_network_register(C):
  17. * Register a new machine key with the Tarsnap server.
  18. */
  19. int
  20. keygen_network_register(struct register_internal * C)
  21. {
  22. NETPACKET_CONNECTION * NPC;
  23. C->done = 0;
  24. C->donechallenge = 0;
  25. C->machinenum = (uint64_t)(-1);
  26. /* Open netpacket connection. */
  27. if ((NPC = netpacket_open(USERAGENT)) == NULL)
  28. goto err2;
  29. /* Ask the netpacket layer to send a request and get a response. */
  30. if (netpacket_op(NPC, callback_register_send, C))
  31. goto err3;
  32. /* Run event loop until an error occurs or we're done. */
  33. if (network_spin(&C->done))
  34. goto err3;
  35. /* Close netpacket connection. */
  36. if (netpacket_close(NPC))
  37. goto err2;
  38. /*
  39. * If we didn't respond to a challenge, the server's response must
  40. * have been a "no such user" error.
  41. */
  42. if ((C->donechallenge == 0) && (C->status != 1)) {
  43. netproto_printerr(NETPROTO_STATUS_PROTERR);
  44. goto err1;
  45. }
  46. /* The machine number should be -1 iff the status is nonzero. */
  47. if (((C->machinenum == (uint64_t)(-1)) && (C->status == 0)) ||
  48. ((C->machinenum != (uint64_t)(-1)) && (C->status != 0))) {
  49. netproto_printerr(NETPROTO_STATUS_PROTERR);
  50. goto err1;
  51. }
  52. /* Parse status returned by server. */
  53. switch (C->status) {
  54. case 0:
  55. /* Success! */
  56. break;
  57. case 1:
  58. warn0("No such user: %s", C->user);
  59. break;
  60. case 2:
  61. warn0("Incorrect password");
  62. break;
  63. case 3:
  64. warn0("Cannot register with server: "
  65. "Account balance for user %s is not positive", C->user);
  66. break;
  67. default:
  68. netproto_printerr(NETPROTO_STATUS_PROTERR);
  69. goto err2;
  70. }
  71. /* Shut down the network event loop. */
  72. network_fini();
  73. /* Success! */
  74. return (0);
  75. err3:
  76. netpacket_close(NPC);
  77. err2:
  78. warnp("Error registering with server");
  79. err1:
  80. /* Shut down the network event loop. */
  81. network_fini();
  82. /* Failure! */
  83. return (-1);
  84. }
  85. static int
  86. callback_register_send(void * cookie, NETPACKET_CONNECTION * NPC)
  87. {
  88. struct register_internal * C = cookie;
  89. /* Tell the server which user is trying to add a machine. */
  90. return (netpacket_register_request(NPC, C->user,
  91. callback_register_challenge));
  92. }
  93. static int
  94. callback_register_challenge(void * cookie, NETPACKET_CONNECTION * NPC,
  95. int status, uint8_t packettype, const uint8_t * packetbuf,
  96. size_t packetlen)
  97. {
  98. struct register_internal * C = cookie;
  99. uint8_t pub[CRYPTO_DH_PUBLEN];
  100. uint8_t priv[CRYPTO_DH_PRIVLEN];
  101. uint8_t K[CRYPTO_DH_KEYLEN];
  102. uint8_t keys[96];
  103. /* Handle errors. */
  104. if (status != NETWORK_STATUS_OK) {
  105. netproto_printerr(status);
  106. goto err0;
  107. }
  108. /*
  109. * Make sure we received the right type of packet. It is legal for
  110. * the server to send back a NETPACKET_REGISTER_RESPONSE at this
  111. * point; call callback_register_response to handle those. Note that
  112. * NETPACKET_REGISTER_RESPONSE at this point must be a "no such user"
  113. * response; we verify this in callback_register_response.
  114. */
  115. if (packettype == NETPACKET_REGISTER_RESPONSE)
  116. return (callback_register_response(cookie, NPC, status,
  117. packettype, packetbuf, packetlen));
  118. else if (packettype != NETPACKET_REGISTER_CHALLENGE) {
  119. netproto_printerr(NETPROTO_STATUS_PROTERR);
  120. goto err0;
  121. }
  122. /* Generate DH parameters from the password and salt. */
  123. if (crypto_passwd_to_dh(C->passwd, packetbuf, pub, priv)) {
  124. warnp("Could not generate DH parameter from password");
  125. goto err0;
  126. }
  127. /* Compute shared key. */
  128. if (crypto_dh_compute(&packetbuf[32], priv, K))
  129. goto err0;
  130. if (crypto_hash_data(CRYPTO_KEY_HMAC_SHA256, K, CRYPTO_DH_KEYLEN,
  131. C->register_key)) {
  132. warn0("Programmer error: "
  133. "SHA256 should never fail");
  134. goto err0;
  135. }
  136. /* Export access keys. */
  137. if (crypto_keys_raw_export_auth(keys))
  138. goto err0;
  139. /* Send challenge response packet. */
  140. if (netpacket_register_cha_response(NPC, keys, C->name,
  141. C->register_key, callback_register_response))
  142. goto err0;
  143. /* We've responded to a challenge. */
  144. C->donechallenge = 1;
  145. /* Success! */
  146. return (0);
  147. err0:
  148. /* Failure! */
  149. return (-1);
  150. }
  151. static int
  152. callback_register_response(void * cookie, NETPACKET_CONNECTION * NPC,
  153. int status, uint8_t packettype, const uint8_t * packetbuf,
  154. size_t packetlen)
  155. {
  156. struct register_internal * C = cookie;
  157. uint8_t hmac_actual[32];
  158. (void)NPC; /* UNUSED */
  159. (void)packetlen; /* UNUSED */
  160. /* Handle errors. */
  161. if (status != NETWORK_STATUS_OK) {
  162. netproto_printerr(status);
  163. goto err0;
  164. }
  165. /* Make sure we received the right type of packet. */
  166. if (packettype != NETPACKET_REGISTER_RESPONSE)
  167. goto err1;
  168. /*
  169. * If the challenge has not been responded to (i.e. this packet
  170. * arrived in response to a NETPACKET_REGISTER_REQUEST packet), this
  171. * should be a "no such user" response.
  172. */
  173. if ((C->donechallenge == 0) && (packetbuf[0] != 1))
  174. goto err1;
  175. /* Verify packet hmac. */
  176. if ((packetbuf[0] == 0) || (packetbuf[0] == 3)) {
  177. crypto_hash_data_key_2(C->register_key, 32, &packettype, 1,
  178. packetbuf, 9, hmac_actual);
  179. } else {
  180. memset(hmac_actual, 0, 32);
  181. }
  182. if (crypto_verify_bytes(hmac_actual, &packetbuf[9], 32))
  183. goto err1;
  184. /* Record status code and machine number returned by server. */
  185. C->status = packetbuf[0];
  186. C->machinenum = be64dec(&packetbuf[1]);
  187. /* We have received a response. */
  188. C->done = 1;
  189. /* Success! */
  190. return (0);
  191. err1:
  192. netproto_printerr(NETPROTO_STATUS_PROTERR);
  193. err0:
  194. /* Failure! */
  195. return (-1);
  196. }