Project

General

Profile

Feature #11356 ยป 0001-add-ecdh-support.patch

tenderlovemaking (Aaron Patterson), 07/15/2015 09:10 PM

View differences:

ext/openssl/ossl_ssl.c
65 65
#define ossl_sslctx_get_cert_store(o)    	rb_iv_get((o),"@cert_store")
66 66
#define ossl_sslctx_get_extra_cert(o)    	rb_iv_get((o),"@extra_chain_cert")
67 67
#define ossl_sslctx_get_client_cert_cb(o) 	rb_iv_get((o),"@client_cert_cb")
68
#define ossl_sslctx_get_tmp_ecdh_cb(o)          rb_iv_get((o),"@tmp_ecdh_callback")
68 69
#define ossl_sslctx_get_tmp_dh_cb(o)     	rb_iv_get((o),"@tmp_dh_callback")
69 70
#define ossl_sslctx_get_sess_id_ctx(o)   	rb_iv_get((o),"@session_id_context")
70 71

  
......
74 75
    "verify_callback", "options", "cert_store", "extra_chain_cert",
75 76
    "client_cert_cb", "tmp_dh_callback", "session_id_context",
76 77
    "session_get_cb", "session_new_cb", "session_remove_cb",
78
    "tmp_ecdh_callback",
77 79
#ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME
78 80
    "servername_cb",
79 81
#endif
......
89 91
#define ossl_ssl_get_x509(o)         rb_iv_get((o),"@x509")
90 92
#define ossl_ssl_get_key(o)          rb_iv_get((o),"@key")
91 93
#define ossl_ssl_get_tmp_dh(o)       rb_iv_get((o),"@tmp_dh")
94
#define ossl_ssl_get_tmp_ecdh(o)     rb_iv_get((o),"@tmp_ecdh")
92 95

  
93 96
#define ossl_ssl_set_io(o,v)         rb_iv_set((o),"@io",(v))
94 97
#define ossl_ssl_set_ctx(o,v)        rb_iv_set((o),"@context",(v))
......
96 99
#define ossl_ssl_set_x509(o,v)       rb_iv_set((o),"@x509",(v))
97 100
#define ossl_ssl_set_key(o,v)        rb_iv_set((o),"@key",(v))
98 101
#define ossl_ssl_set_tmp_dh(o,v)     rb_iv_set((o),"@tmp_dh",(v))
102
#define ossl_ssl_set_tmp_ecdh(o,v)   rb_iv_set((o),"@tmp_ecdh",(v))
99 103

  
100 104
static const char *ossl_ssl_attr_readers[] = { "io", "context", };
101 105
static const char *ossl_ssl_attrs[] = {
......
152 156
int ossl_ssl_ex_ptr_idx;
153 157
int ossl_ssl_ex_client_cert_cb_idx;
154 158
int ossl_ssl_ex_tmp_dh_callback_idx;
159
int ossl_ssl_ex_tmp_ecdh_callback_idx;
155 160

  
156 161
static void
157 162
ossl_sslctx_free(void *ptr)
......
337 342
}
338 343
#endif /* OPENSSL_NO_DH */
339 344

  
345
#if !defined(OPENSSL_NO_EC)
346
static VALUE
347
ossl_call_tmp_ecdh_callback(VALUE *args)
348
{
349
    SSL *ssl;
350
    VALUE cb, ecdh;
351
    EVP_PKEY *pkey;
352

  
353
    GetSSL(args[0], ssl);
354
    cb = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_tmp_ecdh_callback_idx);
355
    if (NIL_P(cb)) return Qfalse;
356
    ecdh = rb_funcall(cb, rb_intern("call"), 3, args[0], args[1], args[2]);
357
    pkey = GetPKeyPtr(ecdh);
358
    if (EVP_PKEY_type(pkey->type) != EVP_PKEY_EC) return Qfalse;
359
    ossl_ssl_set_tmp_ecdh(args[0], ecdh);
360

  
361
    return Qtrue;
362
}
363

  
364
static EC_KEY*
365
ossl_tmp_ecdh_callback(SSL *ssl, int is_export, int keylength)
366
{
367
    VALUE args[3], success;
368

  
369
    args[0] = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx);
370
    args[1] = INT2FIX(is_export);
371
    args[2] = INT2FIX(keylength);
372
    success = rb_protect((VALUE(*)_((VALUE)))ossl_call_tmp_ecdh_callback,
373
                         (VALUE)args, NULL);
374
    if (!RTEST(success)) return NULL;
375

  
376
    return GetPKeyPtr(ossl_ssl_get_tmp_ecdh(args[0]))->pkey.ec;
377
}
378
#endif
379

  
340 380
static int
341 381
ossl_ssl_verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
342 382
{
......
691 731
	SSL_CTX_set_tmp_dh_callback(ctx, ossl_default_tmp_dh_callback);
692 732
    }
693 733
#endif
734

  
735
#if !defined(OPENSSL_NO_EC)
736
    if (RTEST(ossl_sslctx_get_tmp_ecdh_cb(self))){
737
	SSL_CTX_set_tmp_ecdh_callback(ctx, ossl_tmp_ecdh_callback);
738
    }
739
#endif
740

  
694 741
    SSL_CTX_set_ex_data(ctx, ossl_ssl_ex_ptr_idx, (void*)self);
695 742

  
696 743
    val = ossl_sslctx_get_cert_store(self);
......
1234 1281
	SSL_set_ex_data(ssl, ossl_ssl_ex_client_cert_cb_idx, (void*)cb);
1235 1282
	cb = ossl_sslctx_get_tmp_dh_cb(v_ctx);
1236 1283
	SSL_set_ex_data(ssl, ossl_ssl_ex_tmp_dh_callback_idx, (void*)cb);
1284
	cb = ossl_sslctx_get_tmp_ecdh_cb(v_ctx);
1285
	SSL_set_ex_data(ssl, ossl_ssl_ex_tmp_ecdh_callback_idx, (void*)cb);
1237 1286
	SSL_set_info_callback(ssl, ssl_info_cb);
1238 1287
    }
1239 1288

  
......
1926 1975
	SSL_get_ex_new_index(0,(void *)"ossl_ssl_ex_client_cert_cb_idx",0,0,0);
1927 1976
    ossl_ssl_ex_tmp_dh_callback_idx =
1928 1977
	SSL_get_ex_new_index(0,(void *)"ossl_ssl_ex_tmp_dh_callback_idx",0,0,0);
1978
    ossl_ssl_ex_tmp_ecdh_callback_idx =
1979
	SSL_get_ex_new_index(0,(void *)"ossl_ssl_ex_tmp_ecdh_callback_idx",0,0,0);
1929 1980

  
1930 1981
    /* Document-module: OpenSSL::SSL
1931 1982
     *
......
2049 2100
    rb_attr(cSSLContext, rb_intern("client_cert_cb"), 1, 1, Qfalse);
2050 2101

  
2051 2102
    /*
2103
     * A callback invoked when ECDH parameters are required.
2104
     *
2105
     * The callback is invoked with the Session for the key exchange, an
2106
     * flag indicating the use of an export cipher and the keylength
2107
     * required.
2108
     *
2109
     * The callback must return an OpenSSL::PKey::EC instance of the correct
2110
     * key length.
2111
     */
2112
    rb_attr(cSSLContext, rb_intern("tmp_ecdh_callback"), 1, 1, Qfalse);
2113

  
2114
     /*
2052 2115
     * A callback invoked when DH parameters are required.
2053 2116
     *
2054 2117
     * The callback is invoked with the Session for the key exchange, an
test/openssl/test_pair.rb
283 283
    serv.close if serv && !serv.closed?
284 284
  end
285 285

  
286
  def test_ecdh_callback
287
    called = false
288
    ctx2 = OpenSSL::SSL::SSLContext.new
289
    ctx2.ciphers = "ECDH"
290
    ctx2.tmp_ecdh_callback = ->(*args) {
291
      called = true
292
      OpenSSL::PKey::EC.new "prime256v1"
293
    }
294

  
295
    sock1, sock2 = tcp_pair
296

  
297
    s2 = OpenSSL::SSL::SSLSocket.new(sock2, ctx2)
298
    ctx1 = OpenSSL::SSL::SSLContext.new
299
    ctx1.ciphers = "ECDH"
300

  
301
    s1 = OpenSSL::SSL::SSLSocket.new(sock1, ctx1)
302
    th = Thread.new do
303
      begin
304
        rv = s1.connect_nonblock(exception: false)
305
        case rv
306
        when :wait_writable
307
          IO.select(nil, [s1], nil, 5)
308
        when :wait_readable
309
          IO.select([s1], nil, nil, 5)
310
        end
311
      end until rv == s1
312
    end
313

  
314
    accepted = s2.accept
315

  
316
    assert called, 'ecdh callback should be called'
317
  ensure
318
    s1.close if s1
319
    s2.close if s2
320
    sock1.close if sock1
321
    sock2.close if sock2
322
    accepted.close if accepted.respond_to?(:close)
323
  end
324

  
286 325
  def test_connect_accept_nonblock_no_exception
287 326
    ctx2 = OpenSSL::SSL::SSLContext.new
288 327
    ctx2.ciphers = "ADH"
289
-