ssl_ecdh.c 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. /* Copyright (c) 2015, Google Inc.
  2. *
  3. * Permission to use, copy, modify, and/or distribute this software for any
  4. * purpose with or without fee is hereby granted, provided that the above
  5. * copyright notice and this permission notice appear in all copies.
  6. *
  7. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  8. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  9. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
  10. * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  11. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  12. * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  13. * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
  14. #include <openssl/ssl.h>
  15. #include <assert.h>
  16. #include <string.h>
  17. #include <openssl/bn.h>
  18. #include <openssl/bytestring.h>
  19. #include <openssl/curve25519.h>
  20. #include <openssl/ec.h>
  21. #include <openssl/err.h>
  22. #include <openssl/mem.h>
  23. #include <openssl/obj.h>
  24. #include "internal.h"
  25. /* |EC_POINT| implementation. */
  26. static void ssl_ec_point_cleanup(SSL_ECDH_CTX *ctx) {
  27. BIGNUM *private_key = (BIGNUM *)ctx->data;
  28. BN_clear_free(private_key);
  29. }
  30. static int ssl_ec_point_generate_keypair(SSL_ECDH_CTX *ctx, CBB *out) {
  31. assert(ctx->data == NULL);
  32. BIGNUM *private_key = BN_new();
  33. if (private_key == NULL) {
  34. return 0;
  35. }
  36. ctx->data = private_key;
  37. /* Set up a shared |BN_CTX| for all operations. */
  38. BN_CTX *bn_ctx = BN_CTX_new();
  39. if (bn_ctx == NULL) {
  40. return 0;
  41. }
  42. BN_CTX_start(bn_ctx);
  43. int ret = 0;
  44. EC_POINT *public_key = NULL;
  45. EC_GROUP *group = EC_GROUP_new_by_curve_name(ctx->method->nid);
  46. if (group == NULL) {
  47. goto err;
  48. }
  49. /* Generate a private key. */
  50. const BIGNUM *order = EC_GROUP_get0_order(group);
  51. do {
  52. if (!BN_rand_range(private_key, order)) {
  53. goto err;
  54. }
  55. } while (BN_is_zero(private_key));
  56. /* Compute the corresponding public key and serialize it. */
  57. public_key = EC_POINT_new(group);
  58. if (public_key == NULL ||
  59. !EC_POINT_mul(group, public_key, private_key, NULL, NULL, bn_ctx) ||
  60. !EC_POINT_point2cbb(out, group, public_key, POINT_CONVERSION_UNCOMPRESSED,
  61. bn_ctx)) {
  62. goto err;
  63. }
  64. ret = 1;
  65. err:
  66. EC_GROUP_free(group);
  67. EC_POINT_free(public_key);
  68. BN_CTX_end(bn_ctx);
  69. BN_CTX_free(bn_ctx);
  70. return ret;
  71. }
  72. int ssl_ec_point_compute_secret(SSL_ECDH_CTX *ctx, uint8_t **out_secret,
  73. size_t *out_secret_len, uint8_t *out_alert,
  74. const uint8_t *peer_key, size_t peer_key_len) {
  75. BIGNUM *private_key = (BIGNUM *)ctx->data;
  76. assert(private_key != NULL);
  77. *out_alert = SSL_AD_INTERNAL_ERROR;
  78. /* Set up a shared |BN_CTX| for all operations. */
  79. BN_CTX *bn_ctx = BN_CTX_new();
  80. if (bn_ctx == NULL) {
  81. return 0;
  82. }
  83. BN_CTX_start(bn_ctx);
  84. int ret = 0;
  85. EC_GROUP *group = EC_GROUP_new_by_curve_name(ctx->method->nid);
  86. EC_POINT *peer_point = NULL, *result = NULL;
  87. uint8_t *secret = NULL;
  88. if (group == NULL) {
  89. goto err;
  90. }
  91. /* Compute the x-coordinate of |peer_key| * |private_key|. */
  92. peer_point = EC_POINT_new(group);
  93. result = EC_POINT_new(group);
  94. if (peer_point == NULL || result == NULL) {
  95. goto err;
  96. }
  97. BIGNUM *x = BN_CTX_get(bn_ctx);
  98. if (x == NULL) {
  99. goto err;
  100. }
  101. if (!EC_POINT_oct2point(group, peer_point, peer_key, peer_key_len, bn_ctx)) {
  102. *out_alert = SSL_AD_DECODE_ERROR;
  103. goto err;
  104. }
  105. if (!EC_POINT_mul(group, result, NULL, peer_point, private_key, bn_ctx) ||
  106. !EC_POINT_get_affine_coordinates_GFp(group, result, x, NULL, bn_ctx)) {
  107. goto err;
  108. }
  109. /* Encode the x-coordinate left-padded with zeros. */
  110. size_t secret_len = (EC_GROUP_get_degree(group) + 7) / 8;
  111. secret = OPENSSL_malloc(secret_len);
  112. if (secret == NULL || !BN_bn2bin_padded(secret, secret_len, x)) {
  113. goto err;
  114. }
  115. *out_secret = secret;
  116. *out_secret_len = secret_len;
  117. secret = NULL;
  118. ret = 1;
  119. err:
  120. EC_GROUP_free(group);
  121. EC_POINT_free(peer_point);
  122. EC_POINT_free(result);
  123. BN_CTX_end(bn_ctx);
  124. BN_CTX_free(bn_ctx);
  125. OPENSSL_free(secret);
  126. return ret;
  127. }
  128. /* X25119 implementation. */
  129. static void ssl_x25519_cleanup(SSL_ECDH_CTX *ctx) {
  130. if (ctx->data == NULL) {
  131. return;
  132. }
  133. OPENSSL_cleanse(ctx->data, 32);
  134. OPENSSL_free(ctx->data);
  135. }
  136. static int ssl_x25519_generate_keypair(SSL_ECDH_CTX *ctx, CBB *out) {
  137. assert(ctx->data == NULL);
  138. ctx->data = OPENSSL_malloc(32);
  139. if (ctx->data == NULL) {
  140. OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
  141. return 0;
  142. }
  143. uint8_t public_key[32];
  144. X25519_keypair(public_key, (uint8_t *)ctx->data);
  145. return CBB_add_bytes(out, public_key, sizeof(public_key));
  146. }
  147. static int ssl_x25519_compute_secret(SSL_ECDH_CTX *ctx, uint8_t **out_secret,
  148. size_t *out_secret_len, uint8_t *out_alert,
  149. const uint8_t *peer_key,
  150. size_t peer_key_len) {
  151. assert(ctx->data != NULL);
  152. *out_alert = SSL_AD_INTERNAL_ERROR;
  153. uint8_t *secret = OPENSSL_malloc(32);
  154. if (secret == NULL) {
  155. return 0;
  156. }
  157. if (peer_key_len != 32 ||
  158. !X25519(secret, (uint8_t *)ctx->data, peer_key)) {
  159. OPENSSL_free(secret);
  160. *out_alert = SSL_AD_DECODE_ERROR;
  161. OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ECPOINT);
  162. return 0;
  163. }
  164. *out_secret = secret;
  165. *out_secret_len = 32;
  166. return 1;
  167. }
  168. /* Legacy DHE-based implementation. */
  169. static void ssl_dhe_cleanup(SSL_ECDH_CTX *ctx) {
  170. DH_free((DH *)ctx->data);
  171. }
  172. static int ssl_dhe_generate_keypair(SSL_ECDH_CTX *ctx, CBB *out) {
  173. DH *dh = (DH *)ctx->data;
  174. /* The group must have been initialized already, but not the key. */
  175. assert(dh != NULL);
  176. assert(dh->priv_key == NULL);
  177. /* Due to a bug in yaSSL, the public key must be zero padded to the size of
  178. * the prime. */
  179. return DH_generate_key(dh) &&
  180. BN_bn2cbb_padded(out, BN_num_bytes(dh->p), dh->pub_key);
  181. }
  182. static int ssl_dhe_compute_secret(SSL_ECDH_CTX *ctx, uint8_t **out_secret,
  183. size_t *out_secret_len, uint8_t *out_alert,
  184. const uint8_t *peer_key,
  185. size_t peer_key_len) {
  186. DH *dh = (DH *)ctx->data;
  187. assert(dh != NULL);
  188. assert(dh->priv_key != NULL);
  189. *out_alert = SSL_AD_INTERNAL_ERROR;
  190. int secret_len = 0;
  191. uint8_t *secret = NULL;
  192. BIGNUM *peer_point = BN_bin2bn(peer_key, peer_key_len, NULL);
  193. if (peer_point == NULL) {
  194. goto err;
  195. }
  196. secret = OPENSSL_malloc(DH_size(dh));
  197. if (secret == NULL) {
  198. goto err;
  199. }
  200. secret_len = DH_compute_key(secret, peer_point, dh);
  201. if (secret_len <= 0) {
  202. goto err;
  203. }
  204. *out_secret = secret;
  205. *out_secret_len = (size_t)secret_len;
  206. BN_free(peer_point);
  207. return 1;
  208. err:
  209. if (secret_len > 0) {
  210. OPENSSL_cleanse(secret, (size_t)secret_len);
  211. }
  212. OPENSSL_free(secret);
  213. BN_free(peer_point);
  214. return 0;
  215. }
  216. static const SSL_ECDH_METHOD kDHEMethod = {
  217. NID_undef, 0, "",
  218. ssl_dhe_cleanup,
  219. ssl_dhe_generate_keypair,
  220. ssl_dhe_compute_secret,
  221. };
  222. static const SSL_ECDH_METHOD kMethods[] = {
  223. {
  224. NID_X9_62_prime256v1,
  225. SSL_CURVE_SECP256R1,
  226. "P-256",
  227. ssl_ec_point_cleanup,
  228. ssl_ec_point_generate_keypair,
  229. ssl_ec_point_compute_secret,
  230. },
  231. {
  232. NID_secp384r1,
  233. SSL_CURVE_SECP384R1,
  234. "P-384",
  235. ssl_ec_point_cleanup,
  236. ssl_ec_point_generate_keypair,
  237. ssl_ec_point_compute_secret,
  238. },
  239. {
  240. NID_secp521r1,
  241. SSL_CURVE_SECP521R1,
  242. "P-521",
  243. ssl_ec_point_cleanup,
  244. ssl_ec_point_generate_keypair,
  245. ssl_ec_point_compute_secret,
  246. },
  247. {
  248. NID_x25519,
  249. SSL_CURVE_X25519,
  250. "X25519",
  251. ssl_x25519_cleanup,
  252. ssl_x25519_generate_keypair,
  253. ssl_x25519_compute_secret,
  254. },
  255. };
  256. static const SSL_ECDH_METHOD *method_from_curve_id(uint16_t curve_id) {
  257. size_t i;
  258. for (i = 0; i < sizeof(kMethods) / sizeof(kMethods[0]); i++) {
  259. if (kMethods[i].curve_id == curve_id) {
  260. return &kMethods[i];
  261. }
  262. }
  263. return NULL;
  264. }
  265. static const SSL_ECDH_METHOD *method_from_nid(int nid) {
  266. size_t i;
  267. for (i = 0; i < sizeof(kMethods) / sizeof(kMethods[0]); i++) {
  268. if (kMethods[i].nid == nid) {
  269. return &kMethods[i];
  270. }
  271. }
  272. return NULL;
  273. }
  274. const char* SSL_get_curve_name(uint16_t curve_id) {
  275. const SSL_ECDH_METHOD *method = method_from_curve_id(curve_id);
  276. if (method == NULL) {
  277. return NULL;
  278. }
  279. return method->name;
  280. }
  281. int ssl_nid_to_curve_id(uint16_t *out_curve_id, int nid) {
  282. const SSL_ECDH_METHOD *method = method_from_nid(nid);
  283. if (method == NULL) {
  284. return 0;
  285. }
  286. *out_curve_id = method->curve_id;
  287. return 1;
  288. }
  289. int SSL_ECDH_CTX_init(SSL_ECDH_CTX *ctx, uint16_t curve_id) {
  290. SSL_ECDH_CTX_cleanup(ctx);
  291. const SSL_ECDH_METHOD *method = method_from_curve_id(curve_id);
  292. if (method == NULL) {
  293. OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_ELLIPTIC_CURVE);
  294. return 0;
  295. }
  296. ctx->method = method;
  297. return 1;
  298. }
  299. void SSL_ECDH_CTX_init_for_dhe(SSL_ECDH_CTX *ctx, DH *params) {
  300. SSL_ECDH_CTX_cleanup(ctx);
  301. ctx->method = &kDHEMethod;
  302. ctx->data = params;
  303. }
  304. void SSL_ECDH_CTX_cleanup(SSL_ECDH_CTX *ctx) {
  305. if (ctx->method == NULL) {
  306. return;
  307. }
  308. ctx->method->cleanup(ctx);
  309. ctx->method = NULL;
  310. ctx->data = NULL;
  311. }
  312. int SSL_ECDH_CTX_generate_keypair(SSL_ECDH_CTX *ctx, CBB *out_public_key) {
  313. return ctx->method->generate_keypair(ctx, out_public_key);
  314. }
  315. int SSL_ECDH_CTX_compute_secret(SSL_ECDH_CTX *ctx, uint8_t **out_secret,
  316. size_t *out_secret_len, uint8_t *out_alert,
  317. const uint8_t *peer_key, size_t peer_key_len) {
  318. return ctx->method->compute_secret(ctx, out_secret, out_secret_len, out_alert,
  319. peer_key, peer_key_len);
  320. }