Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

set_ecdh_curves.patch 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  1. diff --git a/ext/openssl/extconf.rb b/ext/openssl/extconf.rb
  2. index 76487f7..2a4d3a7 100644
  3. --- a/ext/openssl/extconf.rb
  4. +++ b/ext/openssl/extconf.rb
  5. @@ -93,6 +93,7 @@
  6. have_func("X509_NAME_hash_old")
  7. have_func("X509_STORE_get_ex_data")
  8. have_func("X509_STORE_set_ex_data")
  9. +OpenSSL.check_func_or_macro("SSL_CTX_set_tmp_ecdh_callback", "openssl/ssl.h") # removed
  10. have_func("OBJ_NAME_do_all_sorted")
  11. have_func("SSL_SESSION_get_id")
  12. have_func("SSL_SESSION_cmp")
  13. @@ -109,7 +110,10 @@
  14. have_func("TLSv1_2_method")
  15. have_func("TLSv1_2_server_method")
  16. have_func("TLSv1_2_client_method")
  17. +have_func("EC_curve_nist2nid")
  18. have_func("SSL_CTX_set_alpn_select_cb")
  19. +OpenSSL.check_func_or_macro("SSL_CTX_set1_curves_list", "openssl/ssl.h")
  20. +OpenSSL.check_func_or_macro("SSL_CTX_set_ecdh_auto", "openssl/ssl.h")
  21. have_func("SSL_CTX_set_next_proto_select_cb")
  22. unless have_func("SSL_set_tlsext_host_name", ['openssl/ssl.h'])
  23. have_macro("SSL_set_tlsext_host_name", ['openssl/ssl.h']) && $defs.push("-DHAVE_SSL_SET_TLSEXT_HOST_NAME")
  24. diff --git a/ext/openssl/openssl_missing.c b/ext/openssl/openssl_missing.c
  25. index 31f2d0a..bc61a96 100644
  26. --- a/ext/openssl/openssl_missing.c
  27. +++ b/ext/openssl/openssl_missing.c
  28. @@ -34,6 +34,43 @@ HMAC_CTX_copy(HMAC_CTX *out, HMAC_CTX *in)
  29. #endif /* HAVE_HMAC_CTX_COPY */
  30. #endif /* NO_HMAC */
  31. +/* added in 1.0.2 */
  32. +#if !defined(OPENSSL_NO_EC)
  33. +#if !defined(HAVE_EC_CURVE_NIST2NID)
  34. +static struct {
  35. + const char *name;
  36. + int nid;
  37. +} nist_curves[] = {
  38. + {"B-163", NID_sect163r2},
  39. + {"B-233", NID_sect233r1},
  40. + {"B-283", NID_sect283r1},
  41. + {"B-409", NID_sect409r1},
  42. + {"B-571", NID_sect571r1},
  43. + {"K-163", NID_sect163k1},
  44. + {"K-233", NID_sect233k1},
  45. + {"K-283", NID_sect283k1},
  46. + {"K-409", NID_sect409k1},
  47. + {"K-571", NID_sect571k1},
  48. + {"P-192", NID_X9_62_prime192v1},
  49. + {"P-224", NID_secp224r1},
  50. + {"P-256", NID_X9_62_prime256v1},
  51. + {"P-384", NID_secp384r1},
  52. + {"P-521", NID_secp521r1}
  53. +};
  54. +
  55. +int
  56. +EC_curve_nist2nid(const char *name)
  57. +{
  58. + size_t i;
  59. + for (i = 0; i < (sizeof(nist_curves) / sizeof(nist_curves[0])); i++) {
  60. + if (!strcmp(nist_curves[i].name, name))
  61. + return nist_curves[i].nid;
  62. + }
  63. + return NID_undef;
  64. +}
  65. +#endif
  66. +#endif
  67. +
  68. #if !defined(HAVE_EVP_MD_CTX_CREATE)
  69. EVP_MD_CTX *
  70. EVP_MD_CTX_create(void)
  71. diff --git a/ext/openssl/openssl_missing.h b/ext/openssl/openssl_missing.h
  72. index 955579c..6e2f5b5 100644
  73. --- a/ext/openssl/openssl_missing.h
  74. +++ b/ext/openssl/openssl_missing.h
  75. @@ -70,6 +70,12 @@ void HMAC_CTX_init(HMAC_CTX *ctx);
  76. void HMAC_CTX_copy(HMAC_CTX *out, HMAC_CTX *in);
  77. #endif
  78. +#if !defined(OPENSSL_NO_EC)
  79. +#if !defined(HAVE_EC_CURVE_NIST2NID)
  80. +int EC_curve_nist2nid(const char *);
  81. +#endif
  82. +#endif
  83. +
  84. #if !defined(HAVE_HMAC_CTX_CLEANUP)
  85. void HMAC_CTX_cleanup(HMAC_CTX *ctx);
  86. #endif
  87. diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c
  88. index dc35d5a..cc17a0c 100644
  89. --- a/ext/openssl/ossl_ssl.c
  90. +++ b/ext/openssl/ossl_ssl.c
  91. @@ -161,6 +161,18 @@ ossl_sslctx_s_alloc(VALUE klass)
  92. RTYPEDDATA_DATA(obj) = ctx;
  93. SSL_CTX_set_ex_data(ctx, ossl_ssl_ex_ptr_idx, (void*)obj);
  94. +#if defined(HAVE_SSL_CTX_SET_ECDH_AUTO)
  95. + /* We use SSL_CTX_set1_curves_list() to specify the curve used in ECDH. It
  96. + * allows to specify multiple curve names and OpenSSL will select
  97. + * automatically from them. In OpenSSL 1.0.2, the automatic selection has to
  98. + * be enabled explicitly. But OpenSSL 1.1.0 removed the knob and it is
  99. + * always enabled. To uniform the behavior, we enable the automatic
  100. + * selection also in 1.0.2. Users can still disable ECDH by removing ECDH
  101. + * cipher suites by SSLContext#ciphers=. */
  102. + if (!SSL_CTX_set_ecdh_auto(ctx, 1))
  103. + ossl_raise(eSSLError, "SSL_CTX_set_ecdh_auto");
  104. +#endif
  105. +
  106. return obj;
  107. }
  108. @@ -711,19 +723,33 @@ ossl_sslctx_setup(VALUE self)
  109. #endif
  110. #if !defined(OPENSSL_NO_EC)
  111. - if (RTEST(ossl_sslctx_get_tmp_ecdh_cb(self))){
  112. - SSL_CTX_set_tmp_ecdh_callback(ctx, ossl_tmp_ecdh_callback);
  113. - }
  114. -#endif
  115. + /* We added SSLContext#tmp_ecdh_callback= in Ruby 2.3.0,
  116. + * but SSL_CTX_set_tmp_ecdh_callback() was removed in OpenSSL 1.1.0. */
  117. + if (RTEST(ossl_sslctx_get_tmp_ecdh_cb(self))) {
  118. +# if defined(HAVE_SSL_CTX_SET_TMP_ECDH_CALLBACK)
  119. + rb_warn("#tmp_ecdh_callback= is deprecated; use #ecdh_curves= instead");
  120. + SSL_CTX_set_tmp_ecdh_callback(ctx, ossl_tmp_ecdh_callback);
  121. +# if defined(HAVE_SSL_CTX_SET_ECDH_AUTO)
  122. + /* tmp_ecdh_callback and ecdh_auto conflict; OpenSSL ignores
  123. + * tmp_ecdh_callback. So disable ecdh_auto. */
  124. + if (!SSL_CTX_set_ecdh_auto(ctx, 0))
  125. + ossl_raise(eSSLError, "SSL_CTX_set_ecdh_auto");
  126. +# endif
  127. +# else
  128. + ossl_raise(eSSLError, "OpenSSL does not support tmp_ecdh_callback; "
  129. + "use #ecdh_curves= instead");
  130. +# endif
  131. + }
  132. +#endif /* OPENSSL_NO_EC */
  133. val = ossl_sslctx_get_cert_store(self);
  134. if(!NIL_P(val)){
  135. - /*
  136. - * WORKAROUND:
  137. - * X509_STORE can count references, but
  138. - * X509_STORE_free() doesn't care it.
  139. - * So we won't increment it but mark it by ex_data.
  140. - */
  141. + /*
  142. + * WORKAROUND:
  143. + * X509_STORE can count references, but
  144. + * X509_STORE_free() doesn't care it.
  145. + * So we won't increment it but mark it by ex_data.
  146. + */
  147. store = GetX509StorePtr(val); /* NO NEED TO DUP */
  148. SSL_CTX_set_cert_store(ctx, store);
  149. SSL_CTX_set_ex_data(ctx, ossl_ssl_ex_store_p, (void*)1);
  150. @@ -731,7 +757,7 @@ ossl_sslctx_setup(VALUE self)
  151. val = ossl_sslctx_get_extra_cert(self);
  152. if(!NIL_P(val)){
  153. - rb_block_call(val, rb_intern("each"), 0, 0, ossl_sslctx_add_extra_chain_cert_i, self);
  154. + rb_block_call(val, rb_intern("each"), 0, 0, ossl_sslctx_add_extra_chain_cert_i, self);
  155. }
  156. /* private key may be bundled in certificate file. */
  157. @@ -755,22 +781,21 @@ ossl_sslctx_setup(VALUE self)
  158. val = ossl_sslctx_get_client_ca(self);
  159. if(!NIL_P(val)){
  160. - if (RB_TYPE_P(val, T_ARRAY)) {
  161. - for(i = 0; i < RARRAY_LEN(val); i++){
  162. - client_ca = GetX509CertPtr(RARRAY_AREF(val, i));
  163. - if (!SSL_CTX_add_client_CA(ctx, client_ca)){
  164. - /* Copies X509_NAME => FREE it. */
  165. - ossl_raise(eSSLError, "SSL_CTX_add_client_CA");
  166. - }
  167. - }
  168. - }
  169. - else{
  170. - client_ca = GetX509CertPtr(val); /* NO DUP NEEDED. */
  171. + if (RB_TYPE_P(val, T_ARRAY)) {
  172. + for(i = 0; i < RARRAY_LEN(val); i++){
  173. + client_ca = GetX509CertPtr(RARRAY_AREF(val, i));
  174. + if (!SSL_CTX_add_client_CA(ctx, client_ca)){
  175. + /* Copies X509_NAME => FREE it. */
  176. + ossl_raise(eSSLError, "SSL_CTX_add_client_CA");
  177. + }
  178. + }
  179. + } else {
  180. + client_ca = GetX509CertPtr(val); /* NO DUP NEEDED. */
  181. if (!SSL_CTX_add_client_CA(ctx, client_ca)){
  182. - /* Copies X509_NAME => FREE it. */
  183. - ossl_raise(eSSLError, "SSL_CTX_add_client_CA");
  184. + /* Copies X509_NAME => FREE it. */
  185. + ossl_raise(eSSLError, "SSL_CTX_add_client_CA");
  186. }
  187. - }
  188. + }
  189. }
  190. val = ossl_sslctx_get_ca_file(self);
  191. @@ -778,15 +803,15 @@ ossl_sslctx_setup(VALUE self)
  192. val = ossl_sslctx_get_ca_path(self);
  193. ca_path = NIL_P(val) ? NULL : StringValuePtr(val);
  194. if(ca_file || ca_path){
  195. - if (!SSL_CTX_load_verify_locations(ctx, ca_file, ca_path))
  196. - rb_warning("can't set verify locations");
  197. + if (!SSL_CTX_load_verify_locations(ctx, ca_file, ca_path))
  198. + rb_warning("can't set verify locations");
  199. }
  200. val = ossl_sslctx_get_verify_mode(self);
  201. verify_mode = NIL_P(val) ? SSL_VERIFY_NONE : NUM2INT(val);
  202. SSL_CTX_set_verify(ctx, verify_mode, ossl_ssl_verify_callback);
  203. if (RTEST(ossl_sslctx_get_client_cert_cb(self)))
  204. - SSL_CTX_set_client_cert_cb(ctx, ossl_client_cert_cb);
  205. + SSL_CTX_set_client_cert_cb(ctx, ossl_client_cert_cb);
  206. val = ossl_sslctx_get_timeout(self);
  207. if(!NIL_P(val)) SSL_CTX_set_timeout(ctx, NUM2LONG(val));
  208. @@ -797,26 +822,26 @@ ossl_sslctx_setup(VALUE self)
  209. #ifdef HAVE_SSL_CTX_SET_NEXT_PROTO_SELECT_CB
  210. val = rb_iv_get(self, "@npn_protocols");
  211. if (!NIL_P(val)) {
  212. - rb_iv_set(self, "@_protocols", ssl_encode_npn_protocols(val));
  213. - SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_npn_advertise_cb, (void *) self);
  214. - OSSL_Debug("SSL NPN advertise callback added");
  215. + rb_iv_set(self, "@_protocols", ssl_encode_npn_protocols(val));
  216. + SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_npn_advertise_cb, (void *) self);
  217. + OSSL_Debug("SSL NPN advertise callback added");
  218. }
  219. if (RTEST(rb_iv_get(self, "@npn_select_cb"))) {
  220. - SSL_CTX_set_next_proto_select_cb(ctx, ssl_npn_select_cb, (void *) self);
  221. - OSSL_Debug("SSL NPN select callback added");
  222. + SSL_CTX_set_next_proto_select_cb(ctx, ssl_npn_select_cb, (void *) self);
  223. + OSSL_Debug("SSL NPN select callback added");
  224. }
  225. #endif
  226. #ifdef HAVE_SSL_CTX_SET_ALPN_SELECT_CB
  227. val = rb_iv_get(self, "@alpn_protocols");
  228. if (!NIL_P(val)) {
  229. - VALUE rprotos = ssl_encode_npn_protocols(val);
  230. - SSL_CTX_set_alpn_protos(ctx, (const unsigned char *)StringValueCStr(rprotos), RSTRING_LENINT(rprotos));
  231. - OSSL_Debug("SSL ALPN values added");
  232. + VALUE rprotos = ssl_encode_npn_protocols(val);
  233. + SSL_CTX_set_alpn_protos(ctx, (const unsigned char *)StringValueCStr(rprotos), RSTRING_LENINT(rprotos));
  234. + OSSL_Debug("SSL ALPN values added");
  235. }
  236. if (RTEST(rb_iv_get(self, "@alpn_select_cb"))) {
  237. - SSL_CTX_set_alpn_select_cb(ctx, ssl_alpn_select_cb, (void *) self);
  238. - OSSL_Debug("SSL ALPN select callback added");
  239. + SSL_CTX_set_alpn_select_cb(ctx, ssl_alpn_select_cb, (void *) self);
  240. + OSSL_Debug("SSL ALPN select callback added");
  241. }
  242. #endif
  243. @@ -824,31 +849,31 @@ ossl_sslctx_setup(VALUE self)
  244. val = ossl_sslctx_get_sess_id_ctx(self);
  245. if (!NIL_P(val)){
  246. - StringValue(val);
  247. - if (!SSL_CTX_set_session_id_context(ctx, (unsigned char *)RSTRING_PTR(val),
  248. - RSTRING_LENINT(val))){
  249. - ossl_raise(eSSLError, "SSL_CTX_set_session_id_context");
  250. - }
  251. + StringValue(val);
  252. + if (!SSL_CTX_set_session_id_context(ctx, (unsigned char *)RSTRING_PTR(val),
  253. + RSTRING_LENINT(val))){
  254. + ossl_raise(eSSLError, "SSL_CTX_set_session_id_context");
  255. + }
  256. }
  257. if (RTEST(rb_iv_get(self, "@session_get_cb"))) {
  258. - SSL_CTX_sess_set_get_cb(ctx, ossl_sslctx_session_get_cb);
  259. - OSSL_Debug("SSL SESSION get callback added");
  260. + SSL_CTX_sess_set_get_cb(ctx, ossl_sslctx_session_get_cb);
  261. + OSSL_Debug("SSL SESSION get callback added");
  262. }
  263. if (RTEST(rb_iv_get(self, "@session_new_cb"))) {
  264. - SSL_CTX_sess_set_new_cb(ctx, ossl_sslctx_session_new_cb);
  265. - OSSL_Debug("SSL SESSION new callback added");
  266. + SSL_CTX_sess_set_new_cb(ctx, ossl_sslctx_session_new_cb);
  267. + OSSL_Debug("SSL SESSION new callback added");
  268. }
  269. if (RTEST(rb_iv_get(self, "@session_remove_cb"))) {
  270. - SSL_CTX_sess_set_remove_cb(ctx, ossl_sslctx_session_remove_cb);
  271. - OSSL_Debug("SSL SESSION remove callback added");
  272. + SSL_CTX_sess_set_remove_cb(ctx, ossl_sslctx_session_remove_cb);
  273. + OSSL_Debug("SSL SESSION remove callback added");
  274. }
  275. #ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME
  276. val = rb_iv_get(self, "@servername_cb");
  277. if (!NIL_P(val)) {
  278. SSL_CTX_set_tlsext_servername_callback(ctx, ssl_servername_cb);
  279. - OSSL_Debug("SSL TLSEXT servername callback added");
  280. + OSSL_Debug("SSL TLSEXT servername callback added");
  281. }
  282. #endif
  283. @@ -953,6 +978,87 @@ ossl_sslctx_set_ciphers(VALUE self, VALUE v)
  284. return v;
  285. }
  286. +#if !defined(OPENSSL_NO_EC)
  287. +/*
  288. + * call-seq:
  289. + * ctx.ecdh_curves = curve_list -> curve_list
  290. + *
  291. + * Sets the list of "supported elliptic curves" for this context.
  292. + *
  293. + * For a TLS client, the list is directly used in the Supported Elliptic Curves
  294. + * Extension. For a server, the list is used by OpenSSL to determine the set of
  295. + * shared curves. OpenSSL will pick the most appropriate one from it.
  296. + *
  297. + * Note that this works differently with old OpenSSL (<= 1.0.1). Only one curve
  298. + * can be set, and this has no effect for TLS clients.
  299. + *
  300. + * === Example
  301. + * ctx1 = OpenSSL::SSL::SSLContext.new
  302. + * ctx1.ecdh_curves = "X25519:P-256:P-224"
  303. + * svr = OpenSSL::SSL::SSLServer.new(tcp_svr, ctx1)
  304. + * Thread.new { svr.accept }
  305. + *
  306. + * ctx2 = OpenSSL::SSL::SSLContext.new
  307. + * ctx2.ecdh_curves = "P-256"
  308. + * cli = OpenSSL::SSL::SSLSocket.new(tcp_sock, ctx2)
  309. + * cli.connect
  310. + *
  311. + * p cli.tmp_key.group.curve_name
  312. + * # => "prime256v1" (is an alias for NIST P-256)
  313. + */
  314. +static VALUE
  315. +ossl_sslctx_set_ecdh_curves(VALUE self, VALUE arg)
  316. +{
  317. + SSL_CTX *ctx;
  318. +
  319. + rb_check_frozen(self);
  320. + GetSSLCTX(self, ctx);
  321. + StringValueCStr(arg);
  322. +
  323. +#if defined(HAVE_SSL_CTX_SET1_CURVES_LIST)
  324. + if (!SSL_CTX_set1_curves_list(ctx, RSTRING_PTR(arg)))
  325. + ossl_raise(eSSLError, NULL);
  326. +#else
  327. + /* OpenSSL does not have SSL_CTX_set1_curves_list()... Fallback to
  328. + * SSL_CTX_set_tmp_ecdh(). So only the first curve is used. */
  329. + {
  330. + VALUE curve, splitted;
  331. + EC_KEY *ec;
  332. + int nid;
  333. +
  334. + splitted = rb_str_split(arg, ":");
  335. + if (!RARRAY_LEN(splitted))
  336. + ossl_raise(eSSLError, "invalid input format");
  337. + curve = RARRAY_AREF(splitted, 0);
  338. + StringValueCStr(curve);
  339. +
  340. + /* SSL_CTX_set1_curves_list() accepts NIST names */
  341. + nid = EC_curve_nist2nid(RSTRING_PTR(curve));
  342. + if (nid == NID_undef)
  343. + nid = OBJ_txt2nid(RSTRING_PTR(curve));
  344. + if (nid == NID_undef)
  345. + ossl_raise(eSSLError, "unknown curve name");
  346. +
  347. + ec = EC_KEY_new_by_curve_name(nid);
  348. + if (!ec)
  349. + ossl_raise(eSSLError, NULL);
  350. + EC_KEY_set_asn1_flag(ec, OPENSSL_EC_NAMED_CURVE);
  351. + SSL_CTX_set_tmp_ecdh(ctx, ec);
  352. +# if defined(HAVE_SSL_CTX_SET_ECDH_AUTO)
  353. + /* tmp_ecdh and ecdh_auto conflict. tmp_ecdh is ignored when ecdh_auto
  354. + * is enabled. So disable ecdh_auto. */
  355. + if (!SSL_CTX_set_ecdh_auto(ctx, 0))
  356. + ossl_raise(eSSLError, "SSL_CTX_set_ecdh_auto");
  357. +# endif
  358. + }
  359. +#endif
  360. +
  361. + return arg;
  362. +}
  363. +#else
  364. +#define ossl_sslctx_set_ecdh_curves rb_f_notimplement
  365. +#endif
  366. +
  367. /*
  368. * call-seq:
  369. * ctx.session_add(session) -> true | false
  370. @@ -2075,6 +2181,7 @@ Init_ossl_ssl(void)
  371. */
  372. rb_attr(cSSLContext, rb_intern("client_cert_cb"), 1, 1, Qfalse);
  373. +#if defined(HAVE_SSL_CTX_SET_TMP_ECDH_CALLBACK)
  374. /*
  375. * A callback invoked when ECDH parameters are required.
  376. *
  377. @@ -2082,10 +2189,11 @@ Init_ossl_ssl(void)
  378. * flag indicating the use of an export cipher and the keylength
  379. * required.
  380. *
  381. - * The callback must return an OpenSSL::PKey::EC instance of the correct
  382. - * key length.
  383. + * The callback is deprecated. This does not work with recent versions of
  384. + * OpenSSL. Use OpenSSL::SSL::SSLContext#ecdh_curves= instead.
  385. */
  386. rb_attr(cSSLContext, rb_intern("tmp_ecdh_callback"), 1, 1, Qfalse);
  387. +#endif
  388. /*
  389. * Sets the context in which a session can be reused. This allows
  390. @@ -2221,6 +2329,7 @@ Init_ossl_ssl(void)
  391. rb_define_method(cSSLContext, "ssl_version=", ossl_sslctx_set_ssl_version, 1);
  392. rb_define_method(cSSLContext, "ciphers", ossl_sslctx_get_ciphers, 0);
  393. rb_define_method(cSSLContext, "ciphers=", ossl_sslctx_set_ciphers, 1);
  394. + rb_define_method(cSSLContext, "ecdh_curves=", ossl_sslctx_set_ecdh_curves, 1);
  395. rb_define_method(cSSLContext, "setup", ossl_sslctx_setup, 0);