Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 
 
 
 

378 строки
9.8 KiB

  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/nid.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. static int ssl_ec_point_compute_secret(SSL_ECDH_CTX *ctx,
  73. uint8_t **out_secret,
  74. size_t *out_secret_len,
  75. uint8_t *out_alert,
  76. const uint8_t *peer_key,
  77. size_t peer_key_len) {
  78. BIGNUM *private_key = (BIGNUM *)ctx->data;
  79. assert(private_key != NULL);
  80. *out_alert = SSL_AD_INTERNAL_ERROR;
  81. /* Set up a shared |BN_CTX| for all operations. */
  82. BN_CTX *bn_ctx = BN_CTX_new();
  83. if (bn_ctx == NULL) {
  84. return 0;
  85. }
  86. BN_CTX_start(bn_ctx);
  87. int ret = 0;
  88. EC_GROUP *group = EC_GROUP_new_by_curve_name(ctx->method->nid);
  89. EC_POINT *peer_point = NULL, *result = NULL;
  90. uint8_t *secret = NULL;
  91. if (group == NULL) {
  92. goto err;
  93. }
  94. /* Compute the x-coordinate of |peer_key| * |private_key|. */
  95. peer_point = EC_POINT_new(group);
  96. result = EC_POINT_new(group);
  97. if (peer_point == NULL || result == NULL) {
  98. goto err;
  99. }
  100. BIGNUM *x = BN_CTX_get(bn_ctx);
  101. if (x == NULL) {
  102. goto err;
  103. }
  104. if (!EC_POINT_oct2point(group, peer_point, peer_key, peer_key_len, bn_ctx)) {
  105. *out_alert = SSL_AD_DECODE_ERROR;
  106. goto err;
  107. }
  108. if (!EC_POINT_mul(group, result, NULL, peer_point, private_key, bn_ctx) ||
  109. !EC_POINT_get_affine_coordinates_GFp(group, result, x, NULL, bn_ctx)) {
  110. goto err;
  111. }
  112. /* Encode the x-coordinate left-padded with zeros. */
  113. size_t secret_len = (EC_GROUP_get_degree(group) + 7) / 8;
  114. secret = OPENSSL_malloc(secret_len);
  115. if (secret == NULL || !BN_bn2bin_padded(secret, secret_len, x)) {
  116. goto err;
  117. }
  118. *out_secret = secret;
  119. *out_secret_len = secret_len;
  120. secret = NULL;
  121. ret = 1;
  122. err:
  123. EC_GROUP_free(group);
  124. EC_POINT_free(peer_point);
  125. EC_POINT_free(result);
  126. BN_CTX_end(bn_ctx);
  127. BN_CTX_free(bn_ctx);
  128. OPENSSL_free(secret);
  129. return ret;
  130. }
  131. /* X25119 implementation. */
  132. static void ssl_x25519_cleanup(SSL_ECDH_CTX *ctx) {
  133. if (ctx->data == NULL) {
  134. return;
  135. }
  136. OPENSSL_cleanse(ctx->data, 32);
  137. OPENSSL_free(ctx->data);
  138. }
  139. static int ssl_x25519_generate_keypair(SSL_ECDH_CTX *ctx, CBB *out) {
  140. assert(ctx->data == NULL);
  141. ctx->data = OPENSSL_malloc(32);
  142. if (ctx->data == NULL) {
  143. OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
  144. return 0;
  145. }
  146. uint8_t public_key[32];
  147. X25519_keypair(public_key, (uint8_t *)ctx->data);
  148. return CBB_add_bytes(out, public_key, sizeof(public_key));
  149. }
  150. static int ssl_x25519_compute_secret(SSL_ECDH_CTX *ctx, uint8_t **out_secret,
  151. size_t *out_secret_len, uint8_t *out_alert,
  152. const uint8_t *peer_key,
  153. size_t peer_key_len) {
  154. assert(ctx->data != NULL);
  155. *out_alert = SSL_AD_INTERNAL_ERROR;
  156. uint8_t *secret = OPENSSL_malloc(32);
  157. if (secret == NULL) {
  158. return 0;
  159. }
  160. if (peer_key_len != 32 ||
  161. !X25519(secret, (uint8_t *)ctx->data, peer_key)) {
  162. OPENSSL_free(secret);
  163. *out_alert = SSL_AD_DECODE_ERROR;
  164. OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ECPOINT);
  165. return 0;
  166. }
  167. *out_secret = secret;
  168. *out_secret_len = 32;
  169. return 1;
  170. }
  171. /* Legacy DHE-based implementation. */
  172. static void ssl_dhe_cleanup(SSL_ECDH_CTX *ctx) {
  173. DH_free((DH *)ctx->data);
  174. }
  175. static int ssl_dhe_generate_keypair(SSL_ECDH_CTX *ctx, CBB *out) {
  176. DH *dh = (DH *)ctx->data;
  177. /* The group must have been initialized already, but not the key. */
  178. assert(dh != NULL);
  179. assert(dh->priv_key == NULL);
  180. /* Due to a bug in yaSSL, the public key must be zero padded to the size of
  181. * the prime. */
  182. return DH_generate_key(dh) &&
  183. BN_bn2cbb_padded(out, BN_num_bytes(dh->p), dh->pub_key);
  184. }
  185. static int ssl_dhe_compute_secret(SSL_ECDH_CTX *ctx, uint8_t **out_secret,
  186. size_t *out_secret_len, uint8_t *out_alert,
  187. const uint8_t *peer_key,
  188. size_t peer_key_len) {
  189. DH *dh = (DH *)ctx->data;
  190. assert(dh != NULL);
  191. assert(dh->priv_key != NULL);
  192. *out_alert = SSL_AD_INTERNAL_ERROR;
  193. int secret_len = 0;
  194. uint8_t *secret = NULL;
  195. BIGNUM *peer_point = BN_bin2bn(peer_key, peer_key_len, NULL);
  196. if (peer_point == NULL) {
  197. goto err;
  198. }
  199. secret = OPENSSL_malloc(DH_size(dh));
  200. if (secret == NULL) {
  201. goto err;
  202. }
  203. secret_len = DH_compute_key(secret, peer_point, dh);
  204. if (secret_len <= 0) {
  205. goto err;
  206. }
  207. *out_secret = secret;
  208. *out_secret_len = (size_t)secret_len;
  209. BN_free(peer_point);
  210. return 1;
  211. err:
  212. if (secret_len > 0) {
  213. OPENSSL_cleanse(secret, (size_t)secret_len);
  214. }
  215. OPENSSL_free(secret);
  216. BN_free(peer_point);
  217. return 0;
  218. }
  219. static const SSL_ECDH_METHOD kDHEMethod = {
  220. NID_undef, 0, "",
  221. ssl_dhe_cleanup,
  222. ssl_dhe_generate_keypair,
  223. ssl_dhe_compute_secret,
  224. };
  225. static const SSL_ECDH_METHOD kMethods[] = {
  226. {
  227. NID_X9_62_prime256v1,
  228. SSL_CURVE_SECP256R1,
  229. "P-256",
  230. ssl_ec_point_cleanup,
  231. ssl_ec_point_generate_keypair,
  232. ssl_ec_point_compute_secret,
  233. },
  234. {
  235. NID_secp384r1,
  236. SSL_CURVE_SECP384R1,
  237. "P-384",
  238. ssl_ec_point_cleanup,
  239. ssl_ec_point_generate_keypair,
  240. ssl_ec_point_compute_secret,
  241. },
  242. {
  243. NID_secp521r1,
  244. SSL_CURVE_SECP521R1,
  245. "P-521",
  246. ssl_ec_point_cleanup,
  247. ssl_ec_point_generate_keypair,
  248. ssl_ec_point_compute_secret,
  249. },
  250. {
  251. NID_X25519,
  252. SSL_CURVE_X25519,
  253. "X25519",
  254. ssl_x25519_cleanup,
  255. ssl_x25519_generate_keypair,
  256. ssl_x25519_compute_secret,
  257. },
  258. };
  259. static const SSL_ECDH_METHOD *method_from_curve_id(uint16_t curve_id) {
  260. size_t i;
  261. for (i = 0; i < sizeof(kMethods) / sizeof(kMethods[0]); i++) {
  262. if (kMethods[i].curve_id == curve_id) {
  263. return &kMethods[i];
  264. }
  265. }
  266. return NULL;
  267. }
  268. static const SSL_ECDH_METHOD *method_from_nid(int nid) {
  269. size_t i;
  270. for (i = 0; i < sizeof(kMethods) / sizeof(kMethods[0]); i++) {
  271. if (kMethods[i].nid == nid) {
  272. return &kMethods[i];
  273. }
  274. }
  275. return NULL;
  276. }
  277. const char* SSL_get_curve_name(uint16_t curve_id) {
  278. const SSL_ECDH_METHOD *method = method_from_curve_id(curve_id);
  279. if (method == NULL) {
  280. return NULL;
  281. }
  282. return method->name;
  283. }
  284. int ssl_nid_to_curve_id(uint16_t *out_curve_id, int nid) {
  285. const SSL_ECDH_METHOD *method = method_from_nid(nid);
  286. if (method == NULL) {
  287. return 0;
  288. }
  289. *out_curve_id = method->curve_id;
  290. return 1;
  291. }
  292. int SSL_ECDH_CTX_init(SSL_ECDH_CTX *ctx, uint16_t curve_id) {
  293. SSL_ECDH_CTX_cleanup(ctx);
  294. const SSL_ECDH_METHOD *method = method_from_curve_id(curve_id);
  295. if (method == NULL) {
  296. OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_ELLIPTIC_CURVE);
  297. return 0;
  298. }
  299. ctx->method = method;
  300. return 1;
  301. }
  302. void SSL_ECDH_CTX_init_for_dhe(SSL_ECDH_CTX *ctx, DH *params) {
  303. SSL_ECDH_CTX_cleanup(ctx);
  304. ctx->method = &kDHEMethod;
  305. ctx->data = params;
  306. }
  307. void SSL_ECDH_CTX_cleanup(SSL_ECDH_CTX *ctx) {
  308. if (ctx->method == NULL) {
  309. return;
  310. }
  311. ctx->method->cleanup(ctx);
  312. ctx->method = NULL;
  313. ctx->data = NULL;
  314. }
  315. int SSL_ECDH_CTX_generate_keypair(SSL_ECDH_CTX *ctx, CBB *out_public_key) {
  316. return ctx->method->generate_keypair(ctx, out_public_key);
  317. }
  318. int SSL_ECDH_CTX_compute_secret(SSL_ECDH_CTX *ctx, uint8_t **out_secret,
  319. size_t *out_secret_len, uint8_t *out_alert,
  320. const uint8_t *peer_key, size_t peer_key_len) {
  321. return ctx->method->compute_secret(ctx, out_secret, out_secret_len, out_alert,
  322. peer_key, peer_key_len);
  323. }